package net.myjung.model.editor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.servlet.http.HttpServletRequest;

import net.myjung.Myjung;
import net.myjung.dao.AbstractDaoHibernate;
import net.myjung.dao.IDao;
import net.myjung.exception.MyException;
import net.myjung.generator.AbstractGenerateJavaServlet;
import net.myjung.hibernate.HbnClass;
import net.myjung.hibernate.HbnCollection;
import net.myjung.hibernate.HbnElement;
import net.myjung.hibernate.HbnGenerator;
import net.myjung.hibernate.HbnHibernate_mapping;
import net.myjung.hibernate.HbnId;
import net.myjung.hibernate.HbnKey;
import net.myjung.hibernate.HbnList;
import net.myjung.hibernate.HbnList_index;
import net.myjung.hibernate.HbnMany_to_one;
import net.myjung.hibernate.HbnOne_to_many;
import net.myjung.hibernate.HbnProperty;
import net.myjung.hibernate.HbnSet;
import net.myjung.hibernate.dialect.DB2Dialect;
import net.myjung.interceptor.AbstractManagerInterceptor;
import net.myjung.interceptor.LoggingInterceptor;
import net.myjung.interceptor.TransactionInterceptor;
import net.myjung.maven.MvnActivation;
import net.myjung.maven.MvnBuild;
import net.myjung.maven.MvnConfiguration;
import net.myjung.maven.MvnDependency;
import net.myjung.maven.MvnPlugin;
import net.myjung.maven.MvnProfile;
import net.myjung.maven.MvnProject;
import net.myjung.maven.MvnRepository;
import net.myjung.maven.MvnResource;
import net.myjung.model.AdviceParameters;
import net.myjung.model.BaseObject;
import net.myjung.model.Conds;
import net.myjung.model.CreateObjectParameters;
import net.myjung.model.DeleteObjectListParameters;
import net.myjung.model.DeleteObjectParameters;
import net.myjung.model.Filter;
import net.myjung.model.GetObjectListParameters;
import net.myjung.model.GetObjectParameters;
import net.myjung.model.GetObjectSizeParameters;
import net.myjung.model.MdlAttribute;
import net.myjung.model.MdlClass;
import net.myjung.model.MdlDataSource;
import net.myjung.model.MdlElement;
import net.myjung.model.MdlField;
import net.myjung.model.MdlImplementation;
import net.myjung.model.MdlMethod;
import net.myjung.model.MdlPackage;
import net.myjung.model.MdlParameter;
import net.myjung.model.MdlProject;
import net.myjung.model.MdlText;
import net.myjung.model.MdlTransaction;
import net.myjung.model.MdlWeb;
import net.myjung.model.MdlXmdl;
import net.myjung.model.MyObject;
import net.myjung.model.Order;
import net.myjung.model.SetObjectParameters;
import net.myjung.model.UpdateObjectParameters;
import net.myjung.model.util.IdGenerator;
import net.myjung.spring.SprBean;
import net.myjung.spring.SprBeans;
import net.myjung.spring.SprList;
import net.myjung.spring.SprProp;
import net.myjung.spring.SprProperty;
import net.myjung.transaction.impl.TransactionManager;
import net.myjung.util.ListMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.dialect.MySQL5InnoDBDialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.Oracle10gDialect;
import org.hibernate.dialect.Oracle9iDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import org.springframework.jdbc.support.lob.OracleLobHandler;
import org.springframework.jndi.JndiObjectFactoryBean;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.util.StringUtils;

public class GenerateJavaServlet extends AbstractGenerateJavaServlet {
	protected static Log logger = LogFactory.getLog(GenerateJavaServlet.class);
	private static final long serialVersionUID = 1L;

	protected static final String OPTION_JAVASOURCE = "javaSource";
	protected static final String OPTION_POM = "pom";
	protected static final String OPTION_WEBSOURCE = "webSource";
	protected static final String OPTION_LIBS = "libs";
	protected static final String OPTION_MODELENABLED = "modelEnabled";
	protected static final String OPTION_DAOENABLED = "daoEnabled";
	protected static final String OPTION_AOPENABLED = "aopEnabled";
	protected static final String OPTION_ADMINENABLED = "adminEnabled";

	private static final String CN_MYJUNG = Myjung.class.getName();
	private static final String CN_OBJECT = Object.class.getName();
	private static final String CN_BOOLEAN = Boolean.class.getName();
	private static final String CN_DATE = Date.class.getName();
	private static final String CN_STRING = String.class.getName();
	private static final String CN_LIST = List.class.getName();
	private static final String CN_ARRAYLIST = ArrayList.class.getName();
	private static final String CN_SET = Set.class.getName();
	private static final String CN_HASHSET = HashSet.class.getName();
	private static final String CN_MAP = Map.class.getName();
	private static final String CN_LONG = Long.class.getName();
	private static final String CN_INTEGER = Integer.class.getName();
	private static final String CN_FLOAT = Float.class.getName();
	private static final String CN_DOUBLE = Double.class.getName();
	private static final String CN_BASEOBJECT = BaseObject.class.getName();
	private static final String CN_MYOBJECT = MyObject.class.getName();
	private static final String CN_IDAO = IDao.class.getName();
	private static final String CN_ABSTRACTDAO = AbstractDaoHibernate.class.getName();
	private static final String CN_ABSTRACTINTERCEPTOR = AbstractManagerInterceptor.class.getName();
	private static final String CN_CONDS = Conds.class.getName();
	private static final String CN_FILTER = Filter.class.getName();
	private static final String CN_ORDER = Order.class.getName();
	private static final String CN_GETOBJECTPARAMETERS = GetObjectParameters.class.getName();
	private static final String CN_SETOBJECTPARAMETERS = SetObjectParameters.class.getName();
	private static final String CN_CREATEOBJECTPARAMETERS = CreateObjectParameters.class.getName();
	private static final String CN_UPDATEOBJECTPARAMETERS = UpdateObjectParameters.class.getName();
	private static final String CN_DELETEOBJECTPARAMETERS = DeleteObjectParameters.class.getName();
	private static final String CN_GETOBJECTLISTPARAMETERS = GetObjectListParameters.class.getName();
	private static final String CN_GETOBJECTSIZEPARAMETERS = GetObjectSizeParameters.class.getName();
	private static final String CN_DELETEOBJECTLISTPARAMETERS = DeleteObjectListParameters.class.getName();
	private static final String CN_ADVICEPARAMETERS = AdviceParameters.class.getName();
	private static final String CN_PROXYFACTORYBEAN = ProxyFactoryBean.class.getName();
	private static final String CN_TRANSACTIONMANAGER = TransactionManager.class.getName();
	private static final String CN_TRANSACTIONINTERCEPTER = TransactionInterceptor.class.getName();
	private static final String CN_LOGGINGINTERCEPTER = LoggingInterceptor.class.getName();
	private static final String CN_DRIVERDATASOURCE = "org.apache.commons.dbcp.BasicDataSource";
	private static final String CN_JNDIDATASOURCE = JndiObjectFactoryBean.class.getName();
	private static final String CN_ENTITYMANAGERFACTORY = LocalContainerEntityManagerFactoryBean.class.getName();
	private static final String CN_SESSIONFACTORY = LocalSessionFactoryBean.class.getName();
	private static final String CN_DEFAULTLOBHANDLER = DefaultLobHandler.class.getName();
	private static final String CN_ORACLELOBHANDLER = OracleLobHandler.class.getName();
	private static final String CN_MYSQLDIALECT = MySQLDialect.class.getName();
	private static final String CN_MYSQL5DIALECT = MySQL5InnoDBDialect.class.getName();
	private static final String CN_POSTGRESQLDIALECT = PostgreSQLDialect.class.getName();
	private static final String CN_SQLSERVERDIALECT = SQLServerDialect.class.getName();
	private static final String CN_ORACLE9IDIALECT = Oracle9iDialect.class.getName();
	private static final String CN_ORACLE10GDIALECT = Oracle10gDialect.class.getName();
	private static final String CN_DB2DIALECT = DB2Dialect.class.getName();
	private static final String CN_HIBERNATETRANSACTIONMANAGER = HibernateTransactionManager.class.getName();
	private static final String CN_JPATRANSACTIONMANAGER = JpaTransactionManager.class.getName();
	private static final String CN_JTATRANSACTIONMANAGER = JtaTransactionManager.class.getName();
	private static final String CN_IDGENERATOR = IdGenerator.class.getName();
	private static final String CN_BEANSEXCEPTION = BeansException.class.getName();
	private static final String CN_BEANFACTORY = BeanFactory.class.getName();
	private static final String CN_BEANFACTORYAWARE = BeanFactoryAware.class.getName();

	private static final String AN_MDLCLASS = net.myjung.model.annotation.MdlClass.class.getName();
	private static final String AN_MDLATTRIBUTE = net.myjung.model.annotation.MdlAttribute.class.getName();
	private static final String AN_MDLELEMENT = net.myjung.model.annotation.MdlElement.class.getName();
	private static final String AN_MDLTEXT = net.myjung.model.annotation.MdlText.class.getName();
	private static final String AN_MDLFIELD = net.myjung.model.annotation.MdlField.class.getName();

	private static final String PF_GET = "get";
	private static final String PF_SET = "set";
	private static final String PF_CREATE = "create";
	private static final String PF_UPDATE = "update";
	private static final String PF_DELETE = "delete";
	private static final String PF_BEFORE = "before";
	private static final String PF_AFTER = "after";
	private static final String PF_THROWS = "throws";
	private static final String PF_BEFOREGET = "beforeGet";
	private static final String PF_AFTERGET = "afterGet";
	private static final String PF_THROWSGET = "throwsGet";
	private static final String PF_BEFORESET = "beforeSet";
	private static final String PF_AFTERSET = "afterSet";
	private static final String PF_THROWSSET = "throwsSet";
	private static final String PF_BEFORECREATE = "beforeCreate";
	private static final String PF_AFTERCREATE = "afterCreate";
	private static final String PF_THROWSCREATE = "throwsCreate";
	private static final String PF_BEFOREUPDATE = "beforeUpdate";
	private static final String PF_AFTERUPDATE = "afterUpdate";
	private static final String PF_THROWSUPDATE = "throwsUpdate";
	private static final String PF_BEFOREDELETE = "beforeDelete";
	private static final String PF_AFTERDELETE = "afterDelete";
	private static final String PF_THROWSDELETE = "throwsDelete";
	private static final String PF_INTERFACE = "I";
	private static final String SF_LIST = "List";
	private static final String SF_SIZE = "Size";
	private static final String SF_DAO = "Dao";
	private static final String SF_MANAGER = "Manager";
	private static final String SF_TARGET = "Target";
	private static final String SF_INTERCEPTOR = "Interceptor";
	private static final String SF_FACTORY = "Factory";

	private static MdlClass myobject = null;
	private static ClassInfo myobjectInfo = null;
	private static Object monitor = new Object();
	
	private static String modelLibsPath;
	private static String daoLibsPath;
	private static String adminLibsPath;
	private static String adminSrcsPath;

	public GenerateJavaServlet() {
		super();
		if (myobject != null)
			return;
		synchronized (monitor) {
			if (myobject != null)
				return;
			setMyObject();
		}
	}
	
	protected void refine(MdlXmdl model) {
		if (model == null || Myjung.isEmpty(model.getPackages()))
			return;
		Map<String,MdlPackage> pkgMap = new HashMap<String, MdlPackage>();
		Map<String,MdlClass> classMap = new HashMap<String, MdlClass>();
		List<MdlPackage> removePkgs = new ArrayList<MdlPackage>();
		for (MdlPackage pkg : model.getPackages())
			refine(pkg, pkgMap, classMap, removePkgs);
		if (!Myjung.isEmpty(removePkgs))
			model.getPackages().removeAll(removePkgs);
	}
	private void refine(MdlPackage pkg, Map<String,MdlPackage> pkgMap, Map<String,MdlClass> classMap, List<MdlPackage> removePkgs) {
		String pkgName = pkg.getName();
		boolean remove = pkgMap.containsKey(pkgName);
		if (remove)
			removePkgs.add(pkg);
		else
			pkgMap.put(pkgName, pkg);
		if (Myjung.isEmpty(pkg.getClasses()))
			return;
		List<MdlClass> removeClasses = new ArrayList<MdlClass>();
		for (MdlClass clazz : pkg.getClasses())
			refine(clazz, pkgName, classMap, removeClasses);
		if (!remove && !Myjung.isEmpty(removeClasses))
			pkg.getClasses().removeAll(removeClasses);
	}
	private void refine(MdlClass clazz, String pkgName, Map<String,MdlClass> classMap, List<MdlClass> removeClasses) {
		String className = pkgName + "." + clazz.getName();
		if (classMap.containsKey(className)) {
			removeClasses.add(clazz);
			MdlClass originClass = classMap.get(className);
			for (MdlField field : clazz.getFields()) {
				if (originClass.getFields() == null)
					originClass.setFields(new ArrayList<MdlField>());
				originClass.getFields().add(field);
			}
		} else {
			classMap.put(className, clazz);
		}
	}
	protected void generate(String path, HttpServletRequest request) throws Exception {
		String xmdl = request.getParameter("xmdl");
		if (Myjung.isEmpty(xmdl))
			throw new MyException("xmdl parameter is null");
		
		MdlXmdl model = (MdlXmdl) new MdlXmdl().toObject(xmdl);
		refine(model);
		
		String[] names = StringUtils.tokenizeToStringArray(path, "/\\");
		String name = names[names.length - 1];
		
		Map<String,Object> options = new HashMap<String, Object>();
		options.put(OPTION_JAVASOURCE, Myjung.toBoolean(request.getParameter(OPTION_JAVASOURCE)));
		options.put(OPTION_WEBSOURCE, Myjung.toBoolean(request.getParameter(OPTION_WEBSOURCE)));
		options.put(OPTION_POM, getBoolean(options, OPTION_JAVASOURCE) && Myjung.toBoolean(request.getParameter(OPTION_POM)));
		options.put(OPTION_LIBS, getBoolean(options, OPTION_WEBSOURCE) && Myjung.toBoolean(request.getParameter(OPTION_LIBS)));
		populateOptions(options, model.getProject());
		
		// 변환
		generate(name, path, model, options);
		
		if (getBoolean(options, OPTION_POM) && model.getProject() != null && 
				!Myjung.isEmpty(model.getProject().getGroupId()) && !Myjung.isEmpty(model.getProject().getArtifactId())) {
			MvnProject pom = new MvnProject();
			populatePom(pom, model.getProject(), options);
			Myjung.writeFileString(new StringBuffer(path).append("/pom.xml").toString(), pom.toXMLString(), true);
		}

		if (getBoolean(options, OPTION_LIBS)) {
			String libPath = new StringBuffer(path).append(getString(options, OPTION_WEBAPPPATH)).append("/WEB-INF/lib").toString();
			if (getBoolean(options, OPTION_MODELENABLED))
				Myjung.copyAll(getModelLibsPath(), libPath, true);
			if (getBoolean(options, OPTION_DAOENABLED))
				Myjung.copyAll(getDaoLibsPath(), libPath, true);
			if (getBoolean(options, OPTION_ADMINENABLED))
				Myjung.copyAll(getAdminLibsPath(), libPath, true);
		}
	}
	protected void populateOptions(Map<String,Object> options, MdlProject project) {
		String javaPath = null;
		String webappPath = null;
		String contextConfigPath = null;
		String contextConfigPrefix = null;
		if (project == null) {
			javaPath = "/src";
			webappPath = "/WebContent";
			contextConfigPath = "/WEB-INF";
			contextConfigPrefix = "beans";
		} else {
			javaPath = Myjung.isEmpty(project.getJavaPath())? "/src" : toPath(project.getJavaPath());
			webappPath = Myjung.isEmpty(project.getWebappPath())? "/WebContent" : toPath(project.getWebappPath());
			contextConfigPath = Myjung.isEmpty(project.getContextConfigPath())? "/WEB-INF" : toPath(project.getContextConfigPath());
			contextConfigPrefix = Myjung.isEmpty(project.getContextConfigPrefix())? "beans" : toPath(project.getContextConfigPrefix());
		}
		options.put(OPTION_JAVAPATH, javaPath);
		options.put(OPTION_WEBAPPPATH, webappPath);
		options.put(OPTION_CONTEXTCONFIGPATH, contextConfigPath);
		options.put(OPTION_CONTEXTCONFIGPREFIX, contextConfigPrefix);
	}
	protected void populatePom(MvnProject pom, MdlProject project, Map<String,Object> options) {
		pom.setGroupId(project.getGroupId());
		pom.setArtifactId(project.getArtifactId());
		pom.setVersion(Myjung.toString(project.getVersion(), "0.1.0-SNAPSHOT"));
		
		MvnBuild build = new MvnBuild();
		pom.setBuild(build);
		
		String javaPath = getString(options, OPTION_JAVAPATH);
		build.setSourceDirectory(javaPath.startsWith("/")? javaPath.substring(1) : javaPath);
		
		MvnPlugin warPlugin = new MvnPlugin();
		warPlugin.setArtifactId("maven-war-plugin");
		build.addPlugin(warPlugin);
		
		MvnConfiguration warConfig = new MvnConfiguration();
		String webappPath = getString(options, OPTION_WEBAPPPATH);
		warConfig.setWarSourceDirectory(webappPath.startsWith("/")? webappPath.substring(1) : webappPath);
		warPlugin.setConfiguration(warConfig);
		
		MvnPlugin compilerPlugin = new MvnPlugin();
		compilerPlugin.setGroupId("org.apache.maven.plugins");
		compilerPlugin.setArtifactId("maven-compiler-plugin");
		compilerPlugin.setVersion("2.0.2");
		build.addPlugin(compilerPlugin);
		
		MvnResource srcRsc = new MvnResource();
		srcRsc.setDirectory(getString(options, OPTION_JAVAPATH));
		srcRsc.addInclude("**/hbm.xml");
		srcRsc.addExclude("**/*.java");
		build.addResource(srcRsc);
		
		MvnConfiguration compilerConfig = new MvnConfiguration();
		compilerConfig.setSource("1.5");
		compilerConfig.setTarget("1.5");
		compilerPlugin.setConfiguration(compilerConfig);
		
		MvnProfile jdkProfile = new MvnProfile();
		jdkProfile.setId("jdk1.5");
		pom.addProfile(jdkProfile);
		
		MvnActivation jdkAct = new MvnActivation();
		jdkAct.setJdk("1.5");
		jdkProfile.setActivation(jdkAct);
		
		if (!Myjung.isEmpty(project.getMavenRepositoryUrl())) {
			String repoUrl = project.getMavenRepositoryUrl();
			String repoId = StringUtils.replace(repoUrl, "http://", "");
			repoId = StringUtils.replace(repoId, ".", "_");
			repoId = StringUtils.replace(repoId, "/", "_");
			
			MvnRepository repo = new MvnRepository();
			repo.setId(repoId);
			repo.setUrl(repoUrl);
			pom.addRepository(repo);
		}
		
		MvnDependency junitDep = new MvnDependency();
		junitDep.setGroupId("junit");
		junitDep.setArtifactId("junit");
		junitDep.setVersion("3.8.1");
		junitDep.setScope("test");
		pom.addDependency(junitDep);
		
		MvnDependency myjungDep = new MvnDependency();
		myjungDep.setGroupId("net.myjung");
		myjungDep.setArtifactId("myjung");
		myjungDep.setVersion("1.0.9-SNAPSHOT");
		pom.addDependency(myjungDep);
	}

	/**
	 * 모델을 소스로 변환합니다.
	 * @param name: 애플리케이션 이름
	 * @param path: 소스를 변환해 넣을 절대경로
	 * @param model: 모델
	 * @param options: 옵션
	 * @throws Exception
	 */
	private void generate(String name, String path, MdlXmdl model, Map<String, Object> options) throws Exception {
		if (Myjung.isEmpty(model.getPackages()))
			return;
		
		// applicationContext
		SprList hbmList = new SprList();
		SprBeans beans = newBeans(model, hbmList);
		// web.xml
		MdlWeb web = model.getWeb();
		String webXML = null;
		Properties webProps = new Properties();
		if (web != null) {
			webXML = Myjung.toString(web.getXml(), web.getValue());
			if (!Myjung.isEmpty(web.getContextConfigLocation()))
				webProps.setProperty("contextConfigLocation", web.getContextConfigLocation());
		}
		if (!webProps.contains("contextConfigLocation")) {
			webProps.setProperty("contextConfigLocation", 
					new StringBuffer(getString(options, OPTION_CONTEXTCONFIGPATH))
						.append("/").append(getString(options, OPTION_CONTEXTCONFIGPREFIX)).append("*.xml").toString());
		}
		StringBuffer webBuf = openWebBuf(name, webXML, webProps);
		appendOpenSessionInViewFilterDef(webBuf, toPrefix(model));

		StringBuffer adminHeaderBuf = openAdminHeaderBuf();
		
		generate(path, model, beans, hbmList, webBuf, adminHeaderBuf, options);
		
		if (getBoolean(options, OPTION_WEBSOURCE)) {
			String prefix = toPrefix(model);
			
			// write web.xml
			closeWebBuf(webBuf);
			Myjung.writeFileString(new StringBuffer(path).append(getString(options, OPTION_WEBAPPPATH)).append("/WEB-INF/web.xml").toString(), webBuf.toString(), true);
			
			// write web applicationContext
			writeBeansSource(beans, path, prefix, options);
			
			// write admin
			if (getBoolean(options, OPTION_ADMINENABLED)) {
				String adminPath = new StringBuffer(path).append(getString(options, OPTION_WEBAPPPATH)).append("/admin").toString();
				String username = null;
				String password = null;
				if (model.getAdmin() != null) {
					username = model.getAdmin().getUsername();
					password = model.getAdmin().getPassword();
				}
				writeAdminSource(adminPath, adminSrcsPath, adminHeaderBuf, username, password);
			}
		}
	}
	protected void writeBeansSource(SprBeans beans, String path, String suffix, Map<String,Object> options) throws Exception {
		String contextConfigRelPath = getString(options, OPTION_CONTEXTCONFIGPATH);
		if (contextConfigRelPath.indexOf("classpath*:") != -1) {
			String classpath = new StringBuffer("/WEB-INF/classes/").toString();
			contextConfigRelPath = StringUtils.replace(contextConfigRelPath, "classpath*:", classpath);
		}
		Myjung.writeFileString(new StringBuffer(path).append(getString(options, OPTION_WEBAPPPATH))
				.append(contextConfigRelPath).append("/").append(getString(options, OPTION_CONTEXTCONFIGPREFIX))
				.append(Myjung.isEmpty(suffix)? "" : "-" + suffix).append(".xml").toString(), beans.toXMLString(), true);
	}
	protected void writeAdminSource(String adminPath, String adminSrcPath, StringBuffer adminHeaderBuf, 
			String username, String password) throws Exception {
		Myjung.copyAll(adminSrcPath, adminPath, true);

		String adminDefault = newAdminDefaultJspSource(username, password);
		Myjung.writeFileString(new StringBuffer(adminPath).append("/common/include/default4Html.jsp").toString(), 
				adminDefault, true);
		
		adminHeaderBuf.append("\r\n\t</div>");
		adminHeaderBuf.append("\r\n</div>");
		Myjung.writeFileString(new StringBuffer(adminPath).append("/common/jspInclude/header.jsp").toString(), 
				adminHeaderBuf.toString(), true);
	}
	protected void generate(String path, MdlXmdl model, SprBeans beans, SprList hbmList, StringBuffer webBuf, StringBuffer adminHeaderBuf, Map<String, Object> options) throws Exception {
		Map<String,ClassInfo> classInfoMap = new HashMap<String,ClassInfo>();
		classInfoMap.put(CN_MYOBJECT, myobjectInfo);

		// 패키지 맵을 구성한다.
		// 같은 이름의 패키지가 있을 경우 하나로 합친다.
		ListMap<String,MdlPackage> pkgMap = new ListMap<String,MdlPackage>();
		for (MdlPackage obj: model.getPackages()) {
			String name = obj.getName();
			if (!pkgMap.containsKey(name)) {
				pkgMap.put(name, obj);
				continue;
			} else if (Myjung.isEmpty(obj.getClasses())) {
				if (Myjung.isEmpty(obj.getMethods()))
					continue;
				// 메써드 합치기
				MdlPackage preObj = pkgMap.get(name);
				if (preObj.getMethods() == null)
					preObj.setMethods(new ArrayList<MdlMethod>());
				for (MdlMethod method : obj.getMethods())
					preObj.getMethods().add(method);
				continue;
			}
			Map<String,MdlClass> classMap = new HashMap<String,MdlClass>();
			MdlPackage preObj = pkgMap.get(name);
			String prePrefix = Myjung.toUpperCase(Myjung.toNotNull(preObj.getPrefix()), 0);
			for (MdlClass clazz: preObj.getClasses())
				classMap.put(prePrefix + clazz.getName(), clazz);
			String prefix = Myjung.toUpperCase(Myjung.toNotNull(obj.getPrefix()), 0);
			for (MdlClass clazz: obj.getClasses()) {
				String className = prefix + clazz.getName();
				if (classMap.containsKey(className)) {
					if (Myjung.isEmpty(clazz.getFields()))
						continue;
					// 항목 합치기
					MdlClass preClass = classMap.get(className);
					if (preClass.getFields() == null)
						preClass.setFields(new ArrayList<MdlField>());
					for (MdlField field : clazz.getFields())
						preClass.getFields().add(field);
				}
			}
		}
		
		for (MdlPackage obj : pkgMap.values())
			generate(obj, path, model, options, beans, hbmList, webBuf, adminHeaderBuf, classInfoMap);
	}
	
	private void generate(MdlPackage pkg, String path, MdlXmdl model, Map<String,Object> options, 
			SprBeans beans, SprList mappingList, StringBuffer webBuf, StringBuffer adminHeaderBuf, Map<String,ClassInfo> classInfoMap) throws Exception {
		if (Myjung.isEmpty(pkg.getClasses()) && Myjung.isEmpty(pkg.getMethods()))
			return;
		
		if (options.containsKey(OPTION_AOPENABLED))
			options.remove(OPTION_AOPENABLED);
		
		// 자식(modelClassName)/부모(modelSimpleName) 관계
		Map<String,String> childParentMap = populateChildParentMap(pkg);
		// 클래스(modelClassName)/필드(fieldName)/컬럼(columnName) 관계
		Map<String,Map<String,String>> classFieldColumnMap = new HashMap<String,Map<String,String>>();
		// 클래스(modelClassName)/상속(modelClassName) 관계
		Map<String,String> classExtendsMap = new HashMap<String,String>();
		
		// Models
		// <패키지이름/패키지>
		Map<String, MdlPackage> pkgMap = new HashMap<String, MdlPackage>();
		for (MdlPackage obj : model.getPackages())
			pkgMap.put(obj.getName(), obj);
		
		String javaPath = getString(options, OPTION_JAVAPATH);
		
		generateModels(pkg, path, javaPath, classInfoMap, pkgMap, options, childParentMap, classFieldColumnMap, classExtendsMap);

		// DAOs/AOPs/RESTs/Admin
		generateServers(toPrefix(model), pkg, path, javaPath, getString(options, OPTION_WEBAPPPATH), pkgMap, options, classInfoMap, beans,
				mappingList, webBuf, adminHeaderBuf, childParentMap, classFieldColumnMap, classExtendsMap);
	}

	private static String toLowerGroupPrefix(Map<String,MdlPackage> pkgMap, String pkgName) {
		if (!pkgMap.containsKey(pkgName))
			return null;
		MdlPackage pkg = pkgMap.get(pkgName);
		String pkgSimpleName = toSimpleName(pkgName);
		String prefix = getPrefix(pkg);
		String groupPrefix = Myjung.isEmpty(prefix) ? Myjung.toUpperCase(pkgSimpleName, 0) : prefix;
		String lowerGroupPrefix = Myjung.toLowerCase(groupPrefix, 0);
		return lowerGroupPrefix;
	}
	private void generateServers(String modelPrefix, MdlPackage pkg,
			String path, String javaPath, String webappPath, Map<String,MdlPackage> pkgMap, Map<String,Object> options, 
			Map<String,ClassInfo> classInfoMap, SprBeans beans, SprList mappingList, 
			StringBuffer webBuf, StringBuffer adminHeaderBuf, 
			Map<String,String> childParentMap, 
			Map<String,Map<String,String>> classFieldColumnMap, Map<String,String> classExtendsMap) throws Exception {
		String pkgName = pkg.getName();
		String pkgSimpleName = toSimpleName(pkgName);
		String implPkgName = new StringBuffer(pkgName).append(".impl").toString();
		String pkgPath = toPackagePath(path, javaPath, pkgName);
		String prefix = getPrefix(pkg);
		String lowerPrefix = Myjung.isEmpty(prefix) ? "" : Myjung.toLowerCase(prefix, 0);
		String groupPrefix = Myjung.isEmpty(prefix) ? Myjung.toUpperCase(pkgSimpleName, 0) : prefix;
		String lowerGroupPrefix = Myjung.toLowerCase(groupPrefix, 0);
		String exception = new StringBuffer(groupPrefix).append("Exception").toString();
		String exceptionSource = generateException(pkgName, exception);
		String exceptionClassName = new StringBuffer(pkgName).append(".").append(exception).toString();

		HbnHibernate_mapping hbm = new HbnHibernate_mapping();
		hbm.setPackage(pkgName);

		String idaoName = new StringBuffer(PF_INTERFACE).append(groupPrefix).append(SF_DAO).toString();
		String daoName = new StringBuffer(groupPrefix).append(SF_DAO).toString();
		String imngName = new StringBuffer(PF_INTERFACE).append(groupPrefix).append(SF_MANAGER).toString();
		String mngName = new StringBuffer(groupPrefix).append(SF_MANAGER).toString();
		String mngFieldName = Myjung.toLowerCase(mngName, 0);
		String aopName = new StringBuffer(groupPrefix).append(SF_MANAGER).append(SF_INTERCEPTOR).toString();

		ListMap<String, String> idaoImportMap = new ListMap<String, String>();
		String idaoCn = addImportClassName(idaoImportMap, CN_IDAO);
		StringBuffer idaoClassBuf = new StringBuffer("public interface ").append(idaoName).append(" extends ").append(idaoCn);
		StringBuffer idaoMethodsBuf = new StringBuffer();

		ListMap<String, String> daoImportMap = new ListMap<String, String>();
		addImportClassName(daoImportMap, new StringBuffer(pkgName).append(".").append(idaoName).toString());
		String absDaoCn = addImportClassName(daoImportMap, CN_ABSTRACTDAO);
		addImportClassName(daoImportMap, exceptionClassName);
		StringBuffer daoClassBuf = new StringBuffer("public class ").append(daoName);
		daoClassBuf.append(" extends ").append(absDaoCn).append(" implements ").append(idaoName);
		StringBuffer daoMethodsBuf = new StringBuffer();

		ListMap<String, String> imngImportMap = new ListMap<String, String>();
		StringBuffer imngClassBuf = new StringBuffer("public interface ").append(imngName).append(" extends ").append(idaoName);
		StringBuffer imngMethodsBuf = new StringBuffer();

		ListMap<String, String> mngImportMap = new ListMap<String, String>();
		addImportClassName(mngImportMap, new StringBuffer(pkgName).append(".").append(imngName).toString());
		StringBuffer mngClassBuf = new StringBuffer("public class ").append(mngName)
									.append(" extends ").append(daoName).append(" implements ").append(imngName);
		StringBuffer mngMethodsBuf = new StringBuffer();

		ListMap<String, String> aopImportMap = new ListMap<String, String>();
		addImportClassName(aopImportMap, CN_ABSTRACTINTERCEPTOR);
		StringBuffer aopClassBuf = new StringBuffer("public class ").append(
				aopName).append(" extends AbstractManagerInterceptor");
		StringBuffer aopMethodsBuf = new StringBuffer();
		
		adminHeaderBuf.append("\r\n\t\t<a href=\"<%=path%>/admin/?menu=").append(lowerGroupPrefix);
		adminHeaderBuf.append("\"<%=menu.equals(\"").append(lowerGroupPrefix).append("\")? \" class=\\\"menuSelected\\\"\" : \"\"%>>");
		adminHeaderBuf.append(Myjung.toUpperCase(pkgSimpleName, 0)).append("</a>");
		
		StringBuffer adminSubMenuBuf = populateAdminSubMenu();
		String fcName = new StringBuffer(pkgName).append(".").append(groupPrefix).append(SF_FACTORY).toString();
		String fcSimpleName = new StringBuffer(groupPrefix).append(SF_FACTORY).toString();

		List<MdlClass> classes = pkg.getClasses();
		if (!Myjung.isEmpty(classes)) {
			for (MdlClass clazz : classes) {
				if (!clazz.getDaoEnabled())
					continue;

				options.put(OPTION_DAOENABLED, true);
				boolean aop = clazz.getAopEnabled();
				if (aop)
					options.put(OPTION_AOPENABLED, true);
				if (clazz.getAdminEnabled())
					options.put(OPTION_ADMINENABLED, true);

				addImportClassName(idaoImportMap, CN_MAP);
				addImportClassName(daoImportMap, CN_MAP);
				addImportClassName(idaoImportMap, CN_LIST);
				addImportClassName(daoImportMap, CN_LIST);
				addImportClassName(idaoImportMap, CN_CONDS);
				addImportClassName(daoImportMap, CN_CONDS);

				String modelClassSimpleName = clazz.getName();
				String lowerModelClassSimpleName = Myjung.toLowerCase(modelClassSimpleName, 0);
				String modelClassName = new StringBuffer(pkgName).append(".").append(modelClassSimpleName).toString();
				String objName = toObjName(modelClassSimpleName);
				String simpleName = toSimpleName(prefix, objName);
				String className = new StringBuffer(pkgName).append(".").append(simpleName).toString();

				ClassInfo classInfo = classInfoMap.get(className);
				populate(classInfo, classInfoMap);
				
				SprBean classBean = new SprBean();
				String classBeanId = toId(lowerGroupPrefix, objName);
				classBean.setId(classBeanId);
				classBean.setClazz(className);
				beans.addBean(classBean);
				
				if (clazz.getAdminEnabled()) {
					adminSubMenuBuf.append("\r\n<a href=\"?menu=<%=menu%>&submenu=").append(lowerModelClassSimpleName)
									.append("\"<%=submenu.equals(\"").append(lowerModelClassSimpleName)
									.append("\")? \" class=\\\"submenuSelected\\\"\" : \"\"%>\">").append(modelClassSimpleName).append("</a>");
				}

				// Hibernate Class
				HbnClass hbClass = new HbnClass();
				hbm.addClazz(hbClass);
				hbClass.setName(simpleName);
				String tableName = Myjung.isEmpty(clazz.getTable()) ? simpleName : clazz.getTable();
				if (!simpleName.equals(tableName))
					hbClass.setTable(tableName);
				
				Map<String, Integer> indexMap = new HashMap<String, Integer>();
				appendHibernateProperties(childParentMap.containsKey(modelClassName)? prefix + toValidName(childParentMap.get(modelClassName)) : null, 
														hbClass, pkgName, lowerPrefix, className, tableName, 
														clazz, pkgMap, indexMap, classFieldColumnMap, classExtendsMap);

				// Server Sources
				idaoMethodsBuf.append("\r\n\t// ").append(objName).append(" scope begin");
				daoMethodsBuf.append("\r\n\t// ").append(objName).append(" scope begin");
				if (aop)
					aopMethodsBuf.append("\r\n\t// ").append(objName).append(" scope begin");

				addImportClassName(daoImportMap, className);

				idaoMethodsBuf.append("\r\n\tpublic ").append(simpleName).append(" ").append(PF_GET).append(objName);
				idaoMethodsBuf.append("(String id, Map<String,Object> options) throws ").append(exception).append(";");
				daoMethodsBuf.append("\r\n\tpublic ").append(simpleName).append(" ").append(PF_GET).append(objName);
				daoMethodsBuf.append("(String id, Map<String,Object> options) throws ").append(exception).append(" {");
				wrapExceptionHandler(daoMethodsBuf, 
						new StringBuffer("\r\n\t\t\treturn (").append(simpleName).append(") get(").append(simpleName).append(".class, id, options);").toString(), 
						exception, "\t\t");
				daoMethodsBuf.append("\r\n\t}");
				if (aop) {
					appendInterceptor(aopMethodsBuf, PF_BEFOREGET, objName, null, CN_GETOBJECTPARAMETERS, clazz.getBeforeGet(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_AFTERGET, objName, null, CN_GETOBJECTPARAMETERS, clazz.getAfterGet(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_THROWSGET, objName, null, CN_GETOBJECTPARAMETERS, clazz.getThrowsGet(), aopImportMap);
				}

				idaoMethodsBuf.append("\r\n\tpublic ").append(simpleName).append(" ").append(PF_SET).append(objName);
				idaoMethodsBuf.append("(String user, ").append(simpleName).append(" obj, Map<String,Object> options) throws ").append(exception).append(";");
				daoMethodsBuf.append("\r\n\tpublic ").append(simpleName).append(" ").append(PF_SET).append(objName);
				daoMethodsBuf.append("(String user, ").append(simpleName).append(" obj, Map<String,Object> options) throws ").append(exception).append(" {");
				wrapExceptionHandler(daoMethodsBuf, "\r\n\t\t\tset(user, obj, options);", exception, "\t\t");
				daoMethodsBuf.append("\r\n\t\treturn obj;");
				daoMethodsBuf.append("\r\n\t}");
				if (aop) {
					appendInterceptor(aopMethodsBuf, PF_BEFORESET, objName, null, CN_SETOBJECTPARAMETERS, clazz.getBeforeSet(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_AFTERSET, objName, null, CN_SETOBJECTPARAMETERS, clazz.getAfterSet(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_THROWSSET, objName, null, CN_SETOBJECTPARAMETERS, clazz.getThrowsSet(), aopImportMap);
				}

				idaoMethodsBuf.append("\r\n\tpublic ").append(simpleName).append(" ").append(PF_CREATE).append(objName);
				idaoMethodsBuf.append("(String user, ").append(simpleName).append(" obj, Map<String,Object> options) throws ").append(exception).append(";");
				daoMethodsBuf.append("\r\n\tpublic ").append(simpleName).append(" ").append(PF_CREATE).append(objName);
				daoMethodsBuf.append("(String user, ").append(simpleName).append(" obj, Map<String,Object> options) throws ").append(exception).append(" {");
				wrapExceptionHandler(daoMethodsBuf, "\r\n\t\t\tcreate(user, obj, options);", exception, "\t\t");
				daoMethodsBuf.append("\r\n\t\treturn obj;");
				daoMethodsBuf.append("\r\n\t}");
				if (aop) {
					appendInterceptor(aopMethodsBuf, PF_BEFORECREATE, objName, null, CN_CREATEOBJECTPARAMETERS, clazz.getBeforeCreate(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_AFTERCREATE, objName, null, CN_CREATEOBJECTPARAMETERS, clazz.getAfterCreate(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_THROWSCREATE, objName, null, CN_CREATEOBJECTPARAMETERS, clazz.getThrowsCreate(), aopImportMap);
				}

				idaoMethodsBuf.append("\r\n\tpublic ").append(simpleName).append(" ").append(PF_UPDATE).append(objName);
				idaoMethodsBuf.append("(String user, ").append(simpleName).append(" obj, Map<String,Object> options) throws ").append(exception).append(";");
				daoMethodsBuf.append("\r\n\tpublic ").append(simpleName).append(" ").append(PF_UPDATE).append(objName);
				daoMethodsBuf.append("(String user, ").append(simpleName).append(" obj, Map<String,Object> options) throws ").append(exception).append(" {");
				wrapExceptionHandler(daoMethodsBuf, "\r\n\t\t\tupdate(user, obj, options);", exception, "\t\t");
				daoMethodsBuf.append("\r\n\t\treturn obj;");
				daoMethodsBuf.append("\r\n\t}");
				if (aop) {
					appendInterceptor(aopMethodsBuf, PF_BEFOREUPDATE, objName, null, CN_UPDATEOBJECTPARAMETERS, clazz.getBeforeUpdate(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_AFTERUPDATE, objName, null, CN_UPDATEOBJECTPARAMETERS, clazz.getAfterUpdate(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_THROWSUPDATE, objName, null, CN_UPDATEOBJECTPARAMETERS, clazz.getThrowsUpdate(), aopImportMap);
				}

				idaoMethodsBuf.append("\r\n\tpublic ").append(simpleName).append(" ").append(PF_DELETE).append(objName);
				idaoMethodsBuf.append("(String id, Map<String,Object> options) throws ").append(exception).append(";");
				daoMethodsBuf.append("\r\n\tpublic ").append(simpleName).append(" ").append(PF_DELETE).append(objName);
				daoMethodsBuf.append("(String id, Map<String,Object> options) throws ").append(exception).append(" {");
				wrapExceptionHandler(daoMethodsBuf, 
						new StringBuffer("\r\n\t\t\treturn (").append(simpleName).append(") delete(").append(simpleName)
							.append(".class, id, options);").toString(), exception, "\t\t");
				daoMethodsBuf.append("\r\n\t}");
				if (aop) {
					appendInterceptor(aopMethodsBuf, PF_BEFOREDELETE, objName, null, CN_DELETEOBJECTPARAMETERS, clazz.getBeforeDelete(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_AFTERDELETE, objName, null, CN_DELETEOBJECTPARAMETERS, clazz.getAfterDelete(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_THROWSDELETE, objName, null, CN_DELETEOBJECTPARAMETERS, clazz.getThrowsDelete(), aopImportMap);
				}

				idaoMethodsBuf.append("\r\n\tpublic List<").append(simpleName).append("> ").append(PF_GET).append(objName).append(SF_LIST);
				idaoMethodsBuf.append("(Conds conds, Map<String,Object> options) throws ").append(exception).append(";");
				daoMethodsBuf.append("\r\n\tpublic List<").append(simpleName).append("> ").append(PF_GET).append(objName).append(SF_LIST);
				daoMethodsBuf.append("(Conds conds, Map<String,Object> options) throws ").append(exception).append(" {");
				String arrayList = addImportClassName(daoImportMap, CN_ARRAYLIST);
				String baseObject = addImportClassName(daoImportMap, CN_BASEOBJECT);
				wrapExceptionHandler(daoMethodsBuf, 
						new StringBuffer("\r\n\t\t\treturn to").append(objName).append("List(getList(").append(simpleName).append(".class, conds, options));").toString(), exception, "\t\t");
				daoMethodsBuf.append("\r\n\t}");
				if (aop) {
					appendInterceptor(aopMethodsBuf, PF_BEFOREGET, objName, SF_LIST, CN_GETOBJECTLISTPARAMETERS, clazz.getBeforeGetList(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_AFTERGET, objName, SF_LIST, CN_GETOBJECTLISTPARAMETERS, clazz.getAfterGetList(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_THROWSGET, objName, SF_LIST, CN_GETOBJECTLISTPARAMETERS, clazz.getThrowsGetList(), aopImportMap);
				}

				idaoMethodsBuf.append("\r\n\tpublic long ").append(PF_GET).append(objName).append(SF_SIZE);
				idaoMethodsBuf.append("(Conds conds, Map<String,Object> options) throws ").append(exception).append(";");
				daoMethodsBuf.append("\r\n\tpublic long ").append(PF_GET).append(objName).append(SF_SIZE);
				daoMethodsBuf.append("(Conds conds, Map<String,Object> options) throws ").append(exception).append(" {");
				wrapExceptionHandler(daoMethodsBuf, new StringBuffer("\r\n\t\t\treturn getSize(").append(simpleName)
															.append(".class, conds, options);").toString(), exception, "\t\t");
				daoMethodsBuf.append("\r\n\t}");
				if (aop) {
					appendInterceptor(aopMethodsBuf, PF_BEFOREGET, objName, SF_SIZE, CN_GETOBJECTSIZEPARAMETERS, clazz.getBeforeGetSize(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_AFTERGET, objName, SF_SIZE, CN_GETOBJECTSIZEPARAMETERS, clazz.getAfterGetSize(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_THROWSGET, objName, SF_SIZE, CN_GETOBJECTSIZEPARAMETERS, clazz.getThrowsGetSize(), aopImportMap);
				}

				idaoMethodsBuf.append("\r\n\tpublic List<").append(simpleName).append("> ").append(PF_DELETE).append(objName).append(SF_LIST);
				idaoMethodsBuf.append("(Conds conds, Map<String,Object> options) throws ").append(exception).append(";");
				daoMethodsBuf.append("\r\n\tpublic List<").append(simpleName).append("> ").append(PF_DELETE).append(objName).append(SF_LIST);
				daoMethodsBuf.append("(Conds conds, Map<String,Object> options) throws ").append(exception).append(" {");
				wrapExceptionHandler(daoMethodsBuf, 
						new StringBuffer("\r\n\t\t\treturn to").append(objName).append("List(deleteList(").append(simpleName).append(".class, conds, options));").toString(), exception, "\t\t");
				daoMethodsBuf.append("\r\n\t}");
				String myjung = addImportClassName(daoImportMap, CN_MYJUNG);
				daoMethodsBuf.append("\r\n\tprivate static List<").append(simpleName).append("> to").append(objName).append("List(List<").append(baseObject).append("> boList) {");
				daoMethodsBuf.append("\r\n\t\tList<").append(simpleName).append("> list = new ").append(arrayList).append("<").append(simpleName).append(">();");
				daoMethodsBuf.append("\r\n\t\tif (").append(myjung).append(".isEmpty(boList))");
				daoMethodsBuf.append("\r\n\t\t\treturn list;");
				daoMethodsBuf.append("\r\n\t\tfor (").append(baseObject).append(" obj : boList)");
				daoMethodsBuf.append("\r\n\t\t\tlist.add((").append(simpleName).append(") obj);");
				daoMethodsBuf.append("\r\n\t\treturn list;");
				daoMethodsBuf.append("\r\n\t}");
				if (aop) {
					appendInterceptor(aopMethodsBuf, PF_BEFOREDELETE, objName, SF_LIST, CN_DELETEOBJECTLISTPARAMETERS, clazz.getBeforeDeleteList(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_AFTERDELETE, objName, SF_LIST, CN_DELETEOBJECTLISTPARAMETERS, clazz.getAfterDeleteList(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_THROWSDELETE, objName, SF_LIST, CN_DELETEOBJECTLISTPARAMETERS, clazz.getThrowsDeleteList(), aopImportMap);
				}

				idaoMethodsBuf.append("\r\n\t// ").append(objName).append(" scope end\r\n");
				daoMethodsBuf.append("\r\n\t// ").append(objName).append(" scope end\r\n");
				if (aop)
					aopMethodsBuf.append("\r\n\t// ").append(objName).append(" scope end\r\n");
				
				if (getBoolean(options, OPTION_WEBSOURCE) && clazz.getRestEnabled()) {
					String servletName = new StringBuffer(lowerGroupPrefix).append(objName).append("Servlet").toString();
					String submenu = lowerModelClassSimpleName;
					webBuf.append("\r\n\t<servlet>");
					webBuf.append("\r\n\t\t<servlet-name>").append(servletName).append("</servlet-name>");
					webBuf.append("\r\n\t\t<servlet-class>net.myjung.rest.RestServlet</servlet-class>");
					webBuf.append("\r\n\t\t<init-param>");
					webBuf.append("\r\n\t\t\t<param-name>objectName</param-name>");
					webBuf.append("\r\n\t\t\t<param-value>").append(objName).append("</param-value>");
					webBuf.append("\r\n\t\t</init-param>");
					webBuf.append("\r\n\t\t<init-param>");
					webBuf.append("\r\n\t\t\t<param-name>classId</param-name>");
					webBuf.append("\r\n\t\t\t<param-value>").append(classBeanId).append("</param-value>");
					webBuf.append("\r\n\t\t</init-param>");
					webBuf.append("\r\n\t\t<init-param>");
					webBuf.append("\r\n\t\t\t<param-name>idField</param-name>");
					webBuf.append("\r\n\t\t\t<param-value>").append(classInfo.getId().getName()).append("</param-value>");
					webBuf.append("\r\n\t\t</init-param>");
					webBuf.append("\r\n\t\t<init-param>");
					webBuf.append("\r\n\t\t\t<param-name>factoryId</param-name>");
					webBuf.append("\r\n\t\t\t<param-value>").append(Myjung.toLowerCase(fcSimpleName, 0)).append("</param-value>");
					webBuf.append("\r\n\t\t</init-param>");
					webBuf.append("\r\n\t\t<load-on-startup>1</load-on-startup>");
					webBuf.append("\r\n\t</servlet>");
					webBuf.append("\r\n\t<servlet-mapping>");
					webBuf.append("\r\n\t\t<servlet-name>").append(servletName).append("</servlet-name>");
					webBuf.append("\r\n\t\t<url-pattern>/").append(submenu).append("</url-pattern>");
					webBuf.append("\r\n\t\t<url-pattern>/").append(submenu).append(".xml</url-pattern>");
					webBuf.append("\r\n\t\t<url-pattern>/").append(submenu).append("/*</url-pattern>");
					webBuf.append("\r\n\t</servlet-mapping>");
				}
				
				if (getBoolean(options, OPTION_WEBSOURCE) && clazz.getAdminEnabled() && 
						classInfo != null && classInfo.getId() != null && classInfo.getTitle() != null) {
					ListMap<String,String> objsImportMap = new ListMap<String,String>();
					StringBuffer objsBuf = new StringBuffer();
					ListMap<String,String> objsTdsImportMap = new ListMap<String,String>();
					StringBuffer objsTdsBuf = new StringBuffer();
					ListMap<String,String> objImportMap = new ListMap<String,String>();
					StringBuffer objBuf = new StringBuffer();
					ListMap<String,String> createImportMap = new ListMap<String,String>();
					StringBuffer createBuf = new StringBuffer();
					ListMap<String,String> deleteImportMap = new ListMap<String,String>();
					StringBuffer deleteBuf = new StringBuffer();
					
					String titleType = classInfo.getTitle().getType();
					
					objsBuf.append("<%");
					objsBuf.append("\r\nString formId = Myjung.toString(request.getParameter(\"formId\"), \"objsForm\");");
					objsBuf.append("\r\nString method = Myjung.toNotNull(request.getParameter(\"method\"));");
					objsBuf.append("\r\nif (!Myjung.isEmpty(method) && method.equals(\"delete\")) {");
					objsBuf.append("\r\n\tString checkBoxId = new StringBuffer(formId).append(\"_checkBox\").toString();");
					objsBuf.append("\r\n\tString[] ids = request.getParameterValues(checkBoxId);");
					objsBuf.append("\r\n\tif (!Myjung.isEmpty(ids)) {");
					objsBuf.append("\r\n\t\tFilter idFilter = new Filter();");
					objsBuf.append("\r\n\t\tidFilter.setLeftOperand(\"").append(classInfo.getId().getName()).append("\");");
					objsBuf.append("\r\n\t\tfor (String id : ids)");
					objsBuf.append("\r\n\t\t\tidFilter.addRightOperand(id);");
					objsBuf.append("\r\n\t\tConds conds = new Conds();");
					objsBuf.append("\r\n\t\tconds.addFilter(idFilter);");
					String facName = addImportClassName(objsImportMap, fcName);
					objsBuf.append("\r\n\t\t").append(facName).append(".getManager().delete").append(objName).append("List(conds, null);");
					objsBuf.append("\r\n\t}");
					objsBuf.append("\r\n}");
					objsBuf.append("\r\nString id = Myjung.toNotNull(request.getParameter(\"id\"));");
					objsBuf.append("\r\nString _parentId = Myjung.toNotNull(request.getParameter(\"_parentId\"));");
					objsBuf.append("\r\nString type = Myjung.toString(request.getParameter(\"type\"), Myjung.isEmpty(_parentId)? \"\" : \"children\");");
					String condsName = addImportClassName(objsImportMap, CN_CONDS);
					objsBuf.append("\r\n").append(condsName).append(" conds = (").append(condsName).append(") new ").append(condsName)
							.append("().toObject(Myjung.toString(request.getParameter(\"conds\"), \"<conds pageNo=\\\"0\\\" pageSize=\\\"10\\\"/>\"));");
					objsBuf.append("\r\nconds.setPageNo(Myjung.isEmpty(request.getParameter(\"pageNo\"))? conds.getPageNo() : Integer.parseInt(request.getParameter(\"pageNo\")));");
					objsBuf.append("\r\nconds.setPageSize(Myjung.isEmpty(request.getParameter(\"pageSize\"))? conds.getPageSize() : Integer.parseInt(request.getParameter(\"pageSize\")));");
					String orderField = null;
					if (classInfo.getCreated() != null)
						orderField = classInfo.getCreated().getName();
					else if (classInfo.getModified() != null)
						orderField = classInfo.getModified().getName();
					if (orderField != null) {
						String orderName = addImportClassName(objsImportMap, CN_ORDER);
						objsBuf.append("\r\nconds.addOrder(new ").append(orderName).append("(\"").append(orderField).append("\", false));");
					}
					objsBuf.append("\r\nif (!Myjung.isEmpty(_parentId))");
					String filterName = addImportClassName(objsImportMap, CN_FILTER);
					objsBuf.append("\r\n\tconds.addFilter(new ").append(filterName).append("(\"_parent.id\", _parentId));");
					String objsObjClassName = addImportClassName(objsImportMap, className);
					String listName = addImportClassName(objsImportMap, CN_LIST);
					objsBuf.append("\r\n").append(listName).append("<").append(objsObjClassName).append("> objs = null;");
					objsBuf.append("\r\nString divId = new StringBuffer(formId.substring(0, formId.lastIndexOf(\"Form\"))).append(\"Div\").toString();");
					objsBuf.append("\r\nint pageNo = conds.getPageNo();");
					objsBuf.append("\r\nint pageSize = conds.getPageSize();");
					objsBuf.append("\r\nlong totalSize = 0;");
					objsBuf.append("\r\nif (!type.equals(\"children\") || !Myjung.isEmpty(_parentId)) {");
					objsBuf.append("\r\n\tobjs = ").append(facName).append(".getManager().get").append(objName).append("List").append("(conds, null);");
					objsBuf.append("\r\n\ttotalSize = ").append(facName).append(".getManager().get").append(objName).append("Size(conds, null);");
					objsBuf.append("\r\n}");
					objsBuf.append("\r\n%>");
					objsBuf.append("\r\n<jsp:include page=\"/admin/common/jspInclude/pagination.jsp\">");
					objsBuf.append("\r\n\t<jsp:param name=\"formId\" value=\"<%=formId%>\"/>");
					objsBuf.append("\r\n\t<jsp:param name=\"type\" value=\"<%=type%>\"/>");
					objsBuf.append("\r\n\t<jsp:param name=\"pageNo\" value=\"<%=pageNo%>\"/>");
					objsBuf.append("\r\n\t<jsp:param name=\"pageSize\" value=\"<%=pageSize%>\"/>");
					objsBuf.append("\r\n\t<jsp:param name=\"totalSize\" value=\"<%=totalSize%>\"/>");
					objsBuf.append("\r\n</jsp:include>");
					objsBuf.append("\r\n<form id=\"<%=formId%>\" name=\"<%=formId%>\" method=\"post\">");
					objsBuf.append("\r\n\t<input name=\"method\" type=\"hidden\"/>");
					objsBuf.append("\r\n\t<input name=\"id\" type=\"hidden\" value=\"<%=id%>\"/>");
					objsBuf.append("\r\n\t<input name=\"_parentId\" type=\"hidden\" value=\"<%=_parentId%>\"/>");
					objsBuf.append("\r\n\t<input name=\"menu\" type=\"hidden\" value=\"").append(lowerGroupPrefix).append("\"/>");
					objsBuf.append("\r\n\t<input name=\"submenu\" type=\"hidden\" value=\"").append(lowerModelClassSimpleName).append("\"/>");
					objsBuf.append("\r\n\t<input name=\"divId\" type=\"hidden\" value=\"<%=divId%>\"/>");
					objsBuf.append("\r\n\t<input name=\"pageNo\" type=\"hidden\" value=\"<%=pageNo%>\"/>");
					objsBuf.append("\r\n\t<input name=\"pageSize\" type=\"hidden\" value=\"<%=pageSize%>\"/>");
					objsBuf.append("\r\n\t<table>");
					objsBuf.append("\r\n\t\t<thead>");
					objsBuf.append("\r\n\t\t\t<tr class=\"objsRowHeader\">");
					objsBuf.append("\r\n\t\t\t\t<th class=\"shortFieldHeader\"><input name=\"<%=formId%>_checkAllCheckBox\" type=\"checkbox\" onclick=\"Admin.checkAll('<%=formId%>')\"/></th>");
					objsBuf.append("\r\n\t\t\t\t<th class=\"titleFieldHeader\">").append(classInfo.getTitle().getName()).append("</th>");
					if (classInfo.getCreator() != null)
						objsBuf.append("\r\n\t\t\t\t<th class=\"shortFieldHeader\">").append(classInfo.getCreator().getName()).append("</th>");
					if (classInfo.getCreated() != null)
						objsBuf.append("\r\n\t\t\t\t<th class=\"shortFieldHeader\">").append(classInfo.getCreated().getName()).append("</th>");
					if (classInfo.getModifier() != null)
						objsBuf.append("\r\n\t\t\t\t<th class=\"shortFieldHeader\">").append(classInfo.getModifier().getName()).append("</th>");
					if (classInfo.getModified() != null)
						objsBuf.append("\r\n\t\t\t\t<th class=\"shortFieldHeader\">").append(classInfo.getModified().getName()).append("</th>");
					objsBuf.append("\r\n\t\t\t</tr>");
					objsBuf.append("\r\n\t\t</thead>");
					objsBuf.append("\r\n\t\t<tbody>");
					objsBuf.append("\r\n\t\t<%");
					objsBuf.append("\r\n\t\tif (!Myjung.isEmpty(objs)) {");
					objsBuf.append("\r\n\t\t\tfor (").append(objsObjClassName).append(" obj : objs) {");
					objsBuf.append("\r\n\t\t\t%>");
					
					objsTdsBuf.append("<%");
					objsTdsBuf.append("\r\nString formId = Myjung.toString(request.getParameter(\"formId\"), \"objsForm\");");
					objsTdsBuf.append("\r\nString id = Myjung.toNotNull(request.getParameter(\"id\"));");
					String objsTdsObjClassName = addImportClassName(objsTdsImportMap, className);
					objsTdsBuf.append("\r\n").append(objsTdsObjClassName).append(" obj = null;");
					objsTdsBuf.append("\r\nif (Myjung.isEmpty(id)) {");
					objsTdsBuf.append("\r\n\tobj = new ").append(objsTdsObjClassName).append("();");
					objsTdsBuf.append("\r\n} else {");
					String objsTdsFcName = addImportClassName(objsTdsImportMap, fcName);
					objsTdsBuf.append("\r\n\tobj = ").append(objsTdsFcName).append(".getManager().get").append(objName).append("(id, null);");
					objsTdsBuf.append("\r\n\tif (obj == null)");
					objsTdsBuf.append("\r\n\t\tobj = new ").append(objsTdsObjClassName).append("();");
					objsTdsBuf.append("\r\n}");
					objsTdsBuf.append("\r\n%>");
					
					objsBuf.append("\r\n\t\t\t<tr id=\"<%=formId%>_<%=obj.").append(classInfo.getId().getGetter()).append("()%>\" class=\"objsRow\">");
					objsBuf.append("\r\n\t\t\t\t<td class=\"shortField\" nowrap=\"nowrap\"><input name=\"<%=formId%>_checkBox\" type=\"checkbox\" value=\"<%=obj.")
							.append(classInfo.getId().getGetter()).append("()%>\"/></td>");
					objsBuf.append("\r\n\t\t\t\t<td class=\"titleField\" onclick=\"Admin.getObj('").append(lowerGroupPrefix).append("', '")
							.append(lowerModelClassSimpleName).append("', '<%=obj.").append(classInfo.getId().getGetter()).append("()%>')\"><%=");
					if (CN_STRING.equals(titleType))
						objsBuf.append("StringUtils.replace(Myjung.toNotNull(");
					objsBuf.append("obj.").append(classInfo.getTitle().getGetter()).append("()");
					if (CN_STRING.equals(titleType))
						objsBuf.append("), \"&\", \"&amp;\")");
					objsBuf.append("%></td>");
					if (classInfo.getCreator() != null)
						objsBuf.append("\r\n\t\t\t\t<td class=\"shortField\" nowrap=\"nowrap\"><%=Myjung.toNotNull(obj.").append(classInfo.getCreator().getGetter()).append("())%></td>");
					if (classInfo.getCreated() != null)
						objsBuf.append("\r\n\t\t\t\t<td class=\"shortField\" nowrap=\"nowrap\"><%=Myjung.toXsdDateString(obj.").append(classInfo.getCreated().getGetter()).append("())%></td>");
					if (classInfo.getModifier() != null)
						objsBuf.append("\r\n\t\t\t\t<td class=\"shortField\" nowrap=\"nowrap\"><%=Myjung.toNotNull(obj.").append(classInfo.getModifier().getGetter()).append("())%></td>");
					if (classInfo.getModified() != null)
						objsBuf.append("\r\n\t\t\t\t<td class=\"shortField\" nowrap=\"nowrap\"><%=Myjung.toXsdDateString(obj.").append(classInfo.getModified().getGetter()).append("())%></td>");
					objsBuf.append("\r\n\t\t\t</tr>");
					
					objsTdsBuf.append("\r\n\t\t\t\t<td class=\"shortField\" nowrap=\"nowrap\"><input name=\"<%=formId%>_checkBox\" type=\"checkbox\" value=\"<%=obj.")
							.append(classInfo.getId().getGetter()).append("()%>\"/></td>");
					objsTdsBuf.append("\r\n\t\t\t\t<td class=\"titleField\" onclick=\"Admin.getObj('").append(lowerGroupPrefix).append("', '")
							.append(lowerModelClassSimpleName).append("', '<%=obj.").append(classInfo.getId().getGetter()).append("()%>')\"><%=");
					if (CN_STRING.equals(titleType))
						objsTdsBuf.append("StringUtils.replace(Myjung.toNotNull(");
					objsTdsBuf.append("obj.").append(classInfo.getTitle().getGetter()).append("()");
					if (CN_STRING.equals(titleType))
						objsTdsBuf.append("), \"&\", \"&amp;\")");
					objsTdsBuf.append("%></td>");
					if (classInfo.getCreator() != null)
						objsTdsBuf.append("\r\n\t\t\t\t<td class=\"shortField\" nowrap=\"nowrap\"><%=Myjung.toNotNull(obj.").append(classInfo.getCreator().getGetter()).append("())%></td>");
					if (classInfo.getCreated() != null)
						objsTdsBuf.append("\r\n\t\t\t\t<td class=\"shortField\" nowrap=\"nowrap\"><%=Myjung.toXsdDateString(obj.").append(classInfo.getCreated().getGetter()).append("())%></td>");
					if (classInfo.getModifier() != null)
						objsTdsBuf.append("\r\n\t\t\t\t<td class=\"shortField\" nowrap=\"nowrap\"><%=Myjung.toNotNull(obj.").append(classInfo.getModifier().getGetter()).append("())%></td>");
					if (classInfo.getModified() != null)
						objsTdsBuf.append("\r\n\t\t\t\t<td class=\"shortField\" nowrap=\"nowrap\"><%=Myjung.toXsdDateString(obj.").append(classInfo.getModified().getGetter()).append("())%></td>");
					
					objsBuf.append("\r\n\t\t\t<%");
					objsBuf.append("\r\n\t\t\t}");
					objsBuf.append("\r\n\t\t}");
					objsBuf.append("\r\n\t\t%>");
					objsBuf.append("\r\n\t\t</tbody>");
					objsBuf.append("\r\n\t</table>");
					objsBuf.append("\r\n</form>");
					
					objBuf.append("<%");
					objBuf.append("\r\nString id = Myjung.toNotNull(request.getParameter(\"id\"));");
					objBuf.append("\r\nString method = Myjung.toNotNull(request.getParameter(\"method\"));");
					String objClassName = addImportClassName(objImportMap, className);
					objBuf.append("\r\n").append(objClassName).append(" obj = null;");
					objBuf.append("\r\nif (Myjung.isEmpty(method) || method.equals(\"get\")) {");
					String objFcName = addImportClassName(objImportMap, fcName);
					objBuf.append("\r\n\tif (Myjung.isEmpty(id) || (obj = ").append(objFcName).append(".getManager().get").append(objName).append("(id, null)) == null)");
					objBuf.append("\r\n\t\tobj = new ").append(objClassName).append("();");
					objBuf.append("\r\n} else if (method.equals(\"clear\") || method.equals(\"delete\")) {");
					objBuf.append("\r\n\tif (!Myjung.isEmpty(id) && method.equals(\"delete\"))");
					objBuf.append("\r\n\t\t").append(objFcName).append(".getManager().delete").append(objName).append("(id, null);");
					objBuf.append("\r\n\tobj = new ").append(objClassName).append("();");
					objBuf.append("\r\n} else {");
					objBuf.append("\r\n\tif (method.equals(\"create\") || Myjung.isEmpty(id)) {");
					objBuf.append("\r\n\t\tobj = new ").append(objClassName).append("();");
					objBuf.append("\r\n\t\tobj.").append(classInfo.getId().getSetter());
					String idType = classInfo.getId().getType();
					objBuf.append("(Myjung.");
					if (idType.equals(CN_STRING))
						objBuf.append("toString(id, obj.");
					else if (idType.equals(CN_INTEGER))
						objBuf.append("toInteger(id, obj.");
					else if (idType.equals(CN_LONG))
						objBuf.append("toLong(id, obj.");
					objBuf.append(classInfo.getId().getGetter()).append("()));");
					objBuf.append("\r\n\t} else {");
					objBuf.append("\r\n\t\tobj = ").append(objFcName).append(".getManager().get").append(objName).append("(id, null);");
					objBuf.append("\r\n\t}");
					Collection<FieldInfo> objFields = classInfo.getFieldInfoMap().values();
					Collection<FieldInfo> objCols = new ArrayList<FieldInfo>();
					for (FieldInfo objField : objFields) {
						if (!Myjung.isEmpty(objField.getGeneric())) {
							if (!"disabled".equals(objField.getField().getColumn()))
								objCols.add(objField);
							continue;
						}
						if (objField.equals(classInfo.getId()) || 
								objField.equals(classInfo.getCreator()) || objField.equals(classInfo.getCreated()) ||
								objField.equals(classInfo.getModifier()) || objField.equals(classInfo.getModified()))
							continue;
						String type = objField.getType();
						if (type.equals(CN_STRING)) {
							objBuf.append("\r\n\tobj.").append(objField.getSetter()).append("(Myjung.toString(request.getParameter(\"")
									.append(toParameter(objField.getName())).append("\"), obj.").append(objField.getGetter()).append("()));");
						} else if (type.equals(CN_BOOLEAN)) {
							objBuf.append("\r\n\tobj.").append(objField.getSetter()).append("(Myjung.toBoolean(request.getParameter(\"")
									.append(toParameter(objField.getName())).append("\"), obj.").append(objField.getGetter()).append("()));");
						} else if (type.equals(CN_DATE)) {
							objBuf.append("\r\n\tobj.").append(objField.getSetter()).append("(Myjung.toDate(request.getParameter(\"")
									.append(toParameter(objField.getName())).append("\"), obj.").append(objField.getGetter()).append("()));");
						} else if (type.equals(CN_INTEGER)) {
							objBuf.append("\r\n\tobj.").append(objField.getSetter()).append("(Myjung.toInteger(request.getParameter(\"")
									.append(toParameter(objField.getName())).append("\"), obj.").append(objField.getGetter()).append("()));");
						} else if (type.equals(CN_LONG)) {
							objBuf.append("\r\n\tobj.").append(objField.getSetter()).append("(Myjung.toLong(request.getParameter(\"")
									.append(toParameter(objField.getName())).append("\"), obj.").append(objField.getGetter()).append("()));");
						} else if (type.equals(CN_FLOAT)) {
							objBuf.append("\r\n\tobj.").append(objField.getSetter()).append("(Myjung.toFloat(request.getParameter(\"")
									.append(toParameter(objField.getName())).append("\"), obj.").append(objField.getGetter()).append("()));");
						} else if (type.equals(CN_LONG)) {
							objBuf.append("\r\n\tobj.").append(objField.getSetter()).append("(Myjung.toLong(request.getParameter(\"")
									.append(toParameter(objField.getName())).append("\"), obj.").append(objField.getGetter()).append("()));");
						}
					}
					objBuf.append("\r\n\tif (method.equals(\"create\")) {");
					objBuf.append("\r\n\t\t").append(objFcName).append(".getManager().create").append(objName).append("((String) session.getAttribute(\"username\"), obj, null);");
					objBuf.append("\r\n\t} else if (method.equals(\"update\")) {");
					objBuf.append("\r\n\t\t").append(objFcName).append(".getManager().update").append(objName).append("((String) session.getAttribute(\"username\"), obj, null);");
					objBuf.append("\r\n\t} else if (method.equals(\"set\")) {");
					objBuf.append("\r\n\t\t").append(objFcName).append(".getManager().set").append(objName).append("((String) session.getAttribute(\"username\"), obj, null);");
					objBuf.append("\r\n\t}");
					objBuf.append("\r\n}");
					objBuf.append("\r\nid = obj.").append(classInfo.getId().getGetter()).append("() == null? null : obj.").append(classInfo.getId().getGetter()).append("().toString();");
					objBuf.append("\r\n%>");
					objBuf.append("\r\n<form id=\"objForm\" name=\"objForm\" method=\"post\" action=\"<%=path%>/admin/common/action/doObj.jsp\" target=\"ajaxFrame\">");
					objBuf.append("\r\n\t<input name=\"method\" type=\"hidden\"/>");
					objBuf.append("\r\n\t<input name=\"menu\" type=\"hidden\" value=\"").append(lowerGroupPrefix).append("\"/>");
					objBuf.append("\r\n\t<input name=\"submenu\" type=\"hidden\" value=\"").append(lowerModelClassSimpleName).append("\"/>");
					objBuf.append("\r\n\t<table>");
					objBuf.append("\r\n\t\t<tbody>");
					if (classInfo.getParent() != null) {
						String pType = classInfo.getParent().getType();
						if (classInfoMap.containsKey(pType)) {
							ClassInfo pInfo = classInfoMap.get(pType);
							FieldInfo pId = pInfo.getId();
							FieldInfo pTitle = pInfo.getTitle();
							if (pId != null && pTitle != null) {
								objBuf.append("\r\n\t\t\t<tr>");
								objBuf.append("\r\n\t\t\t\t<td class=\"label\">_parent (").append(pInfo.getClazz().getName()).append(")</td>");
								objBuf.append("\r\n\t\t\t\t<td<%=obj.get_parent() == null? \" class=\\\"value\\\"\" : \"\"%>>");
								objBuf.append("\r\n\t\t\t\t\t<%if (obj.get_parent() != null) {%>");
								objBuf.append("\r\n\t\t\t\t\t<a class=\"valueRef\" onclick=\"Admin.getObj('")
										.append(toLowerGroupPrefix(pkgMap, pInfo.getPkg())).append("', '")
										.append(Myjung.toLowerCase(pInfo.getClazz().getName(), 0)).append("', '<%=obj.get_parent().").append(pId.getGetter()).append("()%>')\">");
								objBuf.append("\r\n\t\t\t\t\t\t<%=Myjung.toString(obj.get_parent().").append(pTitle.getGetter())
										.append("(), obj.get_parent().").append(pId.getGetter()).append("().toString())%>");
								objBuf.append("\r\n\t\t\t\t\t</a>");
								objBuf.append("\r\n\t\t\t\t\t<%}%>");
								objBuf.append("\r\n\t\t\t\t\t<input type=\"button\" class=\"valueRefButton\" value=\"ref...\" disabled=\"disabled\"/>");
								objBuf.append("\r\n\t\t\t\t</td>");
								objBuf.append("\r\n\t\t\t</tr>");
							}
						}
					}
					for (FieldInfo objField : objFields) {
						if (!Myjung.isEmpty(objField.getGeneric()))
							continue;
						populateObjField(objBuf, objField, classInfo, classInfoMap, pkgMap);
					}
					objBuf.append("\r\n\t\t</tbody>");
					objBuf.append("\r\n\t</table>");
					objBuf.append("\r\n</form>");
					for (FieldInfo objCol : objCols) {
						String name = objCol.getName();
						if (!classInfoMap.containsKey(objCol.getGeneric()))
							continue;
						ClassInfo childInfo = classInfoMap.get(objCol.getGeneric());
						objBuf.append("\r\n<%String ").append(name).append("Url = new StringBuffer(\"/admin/model/")
								.append(lowerGroupPrefix).append("/").append(Myjung.toLowerCase(childInfo.getClazz().getName(), 0))
								.append("/objs.jsp\").toString();%>");
						objBuf.append("\r\n<div class=\"subObjsWrapper\">");
						objBuf.append("\r\n\t<div class=\"objsScope\">");
						objBuf.append("\r\n\t\t<div class=\"scopeTitle\">").append(name);
						objBuf.append("\r\n\t\t\t<%if (!Myjung.isEmpty(id)) {%>");
						objBuf.append("\r\n\t\t\t<div class=\"scopeTitleButton\">");
						objBuf.append("\r\n\t\t\t\t<input type=\"button\" value=\"new\" class=\"button\" onclick=\"Admin.createObj('").append(name).append("Form')\"");
						objBuf.append("\r\n\t\t\t\t/><input type=\"button\" value=\"delete\" class=\"button\" onclick=\"Admin.deleteObjs('").append(name).append("Form')\"");
						objBuf.append("\r\n\t\t\t\t/>");
						objBuf.append("\r\n\t\t\t</div>");
						objBuf.append("\r\n\t\t\t<%}%>");
						objBuf.append("\r\n\t\t</div>");
						objBuf.append("\r\n\t\t<div id=\"").append(name).append("Div\" class=\"tableWrapper\">");
						objBuf.append("\r\n\t\t\t<jsp:include page=\"<%=").append(name).append("Url%>\">");
						objBuf.append("\r\n\t\t\t\t<jsp:param name=\"id\" value=\"\"/>");
						objBuf.append("\r\n\t\t\t\t<jsp:param name=\"formId\" value=\"").append(name).append("Form\"/>");
						objBuf.append("\r\n\t\t\t\t<jsp:param name=\"type\" value=\"children\"/>");
						objBuf.append("\r\n\t\t\t\t<jsp:param name=\"_parentId\" value=\"<%=id%>\"/>");
						objBuf.append("\r\n\t\t\t\t<jsp:param name=\"conds\" value=\"\"/>");
						objBuf.append("\r\n\t\t\t\t<jsp:param name=\"pageNo\" value=\"<%=0%>\"/>");
						objBuf.append("\r\n\t\t\t\t<jsp:param name=\"pageSize\" value=\"<%=10%>\"/>");
						objBuf.append("\r\n\t\t\t</jsp:include>");
						objBuf.append("\r\n\t\t</div>");
						objBuf.append("\r\n\t</div>");
						objBuf.append("\r\n</div>");
					}
					
					createBuf.append("<%");
					String createClassName = addImportClassName(createImportMap, className);
					createBuf.append("\r\n").append(createClassName).append(" obj = new ").append(createClassName).append("();");
					createBuf.append("\r\nString formId = Myjung.toNotNull(request.getParameter(\"formId\"));");
					createBuf.append("\r\nString _parentId = Myjung.toNull(request.getParameter(\"_parentId\"));");
					createBuf.append("\r\nif (_parentId != null) {");
					String createFcName = addImportClassName(createImportMap, fcName);
					if (classInfo.getParent() != null) {
						String pType = classInfo.getParent().getType();
						if (classInfoMap.containsKey(pType)) {
							ClassInfo pInfo = classInfoMap.get(pType);
							String createPcName = addImportClassName(createImportMap, pType);
							createBuf.append("\r\n\t").append(createPcName).append(" _parent = ").append(createFcName)
										.append(".getManager().get").append(toObjName(pInfo.getClazz().getName())).append("(_parentId, null);");
							createBuf.append("\r\n\tobj.set_parent(_parent);");
						}
					}
					createBuf.append("\r\n}");
					createBuf.append("\r\n").append(createFcName).append(".getManager().create").append(objName).append("((String) session.getAttribute(\"username\"), obj, null);");
					createBuf.append("\r\nif (_parentId == null) {");
					createBuf.append("\r\n\tresponse.sendRedirect(new StringBuffer(path).append(\"/admin/?menu=").append(lowerGroupPrefix)
								.append("&submenu=").append(lowerModelClassSimpleName)
								.append("&id=\").append(obj.").append(classInfo.getId().getGetter()).append("()).append(\"&formId=\").append(formId).toString());");
					createBuf.append("\r\n} else {");
					createBuf.append("\r\n\tresponse.sendRedirect(new StringBuffer(path).append(\"/admin/model/")
								.append(lowerGroupPrefix).append("/").append(lowerModelClassSimpleName)
								.append("/objs.jsp?type=children&_parentId=\").append(_parentId).append(\"&formId=\").append(formId).toString());");
					createBuf.append("\r\n}");
					createBuf.append("\r\n%>");
					
					deleteBuf.append("<%");
					deleteBuf.append("\r\nString formId = Myjung.toNotNull(request.getParameter(\"formId\"));");
					deleteBuf.append("\r\nString[] ids = request.getParameterValues(\"id\");");
					deleteBuf.append("\r\nif (!Myjung.isEmpty(ids)) {");
					String deleteCondsName = addImportClassName(deleteImportMap, CN_CONDS);
					deleteBuf.append("\r\n\t").append(deleteCondsName).append(" conds = new ").append(deleteCondsName).append("();");
					String deleteFilterName = addImportClassName(deleteImportMap, CN_FILTER);
					deleteBuf.append("\r\n\t").append(deleteFilterName).append(" idsFilter = new ").append(deleteFilterName).append("();");
					deleteBuf.append("\r\n\tidsFilter.setLeftOperand(\"").append(classInfo.getId().getName()).append("\");");
					deleteBuf.append("\r\n\tfor (int i=0; i<ids.length; i++)");
					deleteBuf.append("\r\n\t\tidsFilter.addRightOperand(ids[i]);");
					deleteBuf.append("\r\n\tconds.addFilter(idsFilter);");
					String deleteFcName = addImportClassName(deleteImportMap, fcName);
					deleteBuf.append("\r\n\t").append(deleteFcName).append(".getManager().delete").append(objName).append("List(conds, null);");
					deleteBuf.append("\r\n}");
					deleteBuf.append("\r\nString _parentId = Myjung.toNull(request.getParameter(\"_parentId\"));");
					deleteBuf.append("\r\nif (_parentId == null) {");
					deleteBuf.append("\r\n\tresponse.sendRedirect(new StringBuffer(path).append(\"/admin/?menu=").append(lowerGroupPrefix)
								.append("&submenu=").append(lowerModelClassSimpleName).append("\").append(\"&formId=\").append(formId).toString());");
					deleteBuf.append("\r\n} else {");
					deleteBuf.append("\r\n\tresponse.sendRedirect(new StringBuffer(path).append(\"/admin/model/")
								.append(lowerGroupPrefix).append("/").append(lowerModelClassSimpleName)
								.append("/objs.jsp?type=children&_parentId=\").append(_parentId).append(\"&formId=\").append(formId).toString());");
					deleteBuf.append("\r\n}");
					deleteBuf.append("\r\n%>");
					
					String objsJsp = generateJsp(objsImportMap, objsBuf.toString());
					String objsTdsJsp = generateJsp(objsTdsImportMap, objsTdsBuf.toString());
					String objJsp = generateJsp(objImportMap, objBuf.toString());
					String createJsp = generateJsp(createImportMap, createBuf.toString());
					String deleteJsp = generateJsp(deleteImportMap, deleteBuf.toString());
					
					String adminObjPath = new StringBuffer(path).append(webappPath).append("/admin/model/").append(lowerGroupPrefix).append("/").append(lowerModelClassSimpleName).toString();
					String adminActionPath = new StringBuffer(adminObjPath).append("/action").toString();
					Myjung.writeFileString(new StringBuffer(adminObjPath).append("/").append("objs.jsp").toString(), objsJsp, true);
					Myjung.writeFileString(new StringBuffer(adminObjPath).append("/").append("objsTds.jsp").toString(), objsTdsJsp, true);
					Myjung.writeFileString(new StringBuffer(adminObjPath).append("/").append("obj.jsp").toString(), objJsp, true);
					Myjung.writeFileString(new StringBuffer(adminActionPath).append("/").append("create.jsp").toString(), createJsp, true);
					Myjung.writeFileString(new StringBuffer(adminActionPath).append("/").append("delete.jsp").toString(), deleteJsp, true);
				}
			}
		}

		List<MdlMethod> methods = pkg.getMethods();
		if (!Myjung.isEmpty(methods)) {
			for (MdlMethod method : methods) {
				options.put(OPTION_DAOENABLED, true);
				if (method.getAopEnabled())
					options.put(OPTION_AOPENABLED, true);
				if (method.getAdminEnabled())
					options.put(OPTION_ADMINENABLED, true);
				String methodName = method.getName();
				String methodUpperName = Myjung.toUpperCase(methodName, 0);
				String returnType = Myjung.isEmpty(method.getReturns()) ? "void" : toJavaType(method.getReturns(), pkgMap);
				List<MdlParameter> params = method.getParameters();
				String throwType = Myjung.toNull(method.getThrows());
				boolean hasReturn = !returnType.equals("void");
				if (hasReturn) {
					addImportClassName(imngImportMap, returnType);
					returnType = addImportClassName(mngImportMap, returnType);
				}
				if (throwType != null && !throwType.equals("Exception")) {
					addImportClassName(imngImportMap, throwType);
					throwType = addImportClassName(mngImportMap, throwType);
				}
				if (imngMethodsBuf.length() > 0)
					imngMethodsBuf.append("\r\n");
				imngMethodsBuf.append("\tpublic ").append(returnType).append(" ").append(methodName).append("(");
				mngMethodsBuf.append("\r\n\tpublic ").append(returnType).append(" ").append(methodName).append("(");
				if (!Myjung.isEmpty(params)) {
					int i = 0;
					String paramType;
					String paramName;
					for (MdlParameter param : params) {
						paramType = toJavaType(param.getType(), pkgMap);
						paramName = toFieldName(param.getName());
						if (i++ > 0) {
							imngMethodsBuf.append(", ");
							mngMethodsBuf.append(", ");
						}
						imngMethodsBuf.append(addImportClassName(imngImportMap, paramType));
						mngMethodsBuf.append(addImportClassName(imngImportMap, paramType));
						imngMethodsBuf.append(" ");
						mngMethodsBuf.append(" ");
						imngMethodsBuf.append(paramName);
						mngMethodsBuf.append(paramName);
					}
				}
				imngMethodsBuf.append(")");
				mngMethodsBuf.append(")");
				if (throwType != null) {
					imngMethodsBuf.append(" throws ").append(throwType);
					mngMethodsBuf.append(" throws ").append(throwType);
				}
				imngMethodsBuf.append(";");
				mngMethodsBuf.append(" {\r\n");
				appendImplementation(mngMethodsBuf, null, method
						.getImplementation(), mngImportMap, hasReturn);
				mngMethodsBuf.append("\r\n\t}\r\n");

				if (method.getAopEnabled()) {
					appendInterceptor(aopMethodsBuf, PF_BEFORE, methodUpperName, null, CN_ADVICEPARAMETERS, method.getBeforeAdvice(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_AFTER, methodUpperName, null, CN_ADVICEPARAMETERS, method.getAfterAdvice(), aopImportMap);
					appendInterceptor(aopMethodsBuf, PF_THROWS, methodUpperName, null, CN_ADVICEPARAMETERS, method.getThrowsAdvice(), aopImportMap);
					aopMethodsBuf.append("\r\n");
				}
			}
		}

		if (getBoolean(options, OPTION_DAOENABLED)) {
			ListMap<String, String> fcImportMap = new ListMap<String, String>();
			addImportClassName(fcImportMap, CN_BEANSEXCEPTION);
			addImportClassName(fcImportMap, CN_BEANFACTORY);
			addImportClassName(fcImportMap, CN_BEANFACTORYAWARE);
			StringBuffer fcClassBuf = new StringBuffer("public class ").append(fcSimpleName).append(" implements BeanFactoryAware");
			StringBuffer fcFieldsBuf = new StringBuffer("\tprivate static BeanFactory bf = null;");
			fcFieldsBuf.append("\r\n\tprivate static ").append(imngName).append(" ").append(mngFieldName).append(";");
			StringBuffer fcMethodsBuf = new StringBuffer("\tpublic static ").append(imngName).append(" getManager() {");
			fcMethodsBuf.append("\r\n\t\tif (").append(mngFieldName).append(" == null)");
			fcMethodsBuf.append("\r\n\t\t\t").append(mngFieldName).append(" = (").append(imngName).append(") bf.getBean(\"").append(mngFieldName).append("\");");
			fcMethodsBuf.append("\r\n\t\treturn ").append(mngFieldName).append(";");
			fcMethodsBuf.append("\r\n\t}");
			fcMethodsBuf.append("\r\n\tpublic void setBeanFactory(BeanFactory value) throws BeansException {");
			fcMethodsBuf.append("\r\n\t\tbf = value;");
			fcMethodsBuf.append("\r\n\t}");

			SprBean fcBean = new SprBean();
			fcBean.setId(Myjung.toLowerCase(fcSimpleName, 0));
			fcBean.setClazz(fcName);
			beans.addBean(fcBean);

			appendManagerBean(beans, modelPrefix, pkgName, mngName, aopName, pkg.getExternalInterceptorBeanId(), options);

			String idao = toClassSource(pkgName, idaoImportMap.valueList(), idaoClassBuf, null, idaoMethodsBuf);
			String dao = toClassSource(implPkgName, daoImportMap.valueList(), daoClassBuf, null, daoMethodsBuf);
			String imng = toClassSource(pkgName, imngImportMap.valueList(), imngClassBuf, null, imngMethodsBuf);
			String mng = toClassSource(implPkgName, mngImportMap.valueList(), mngClassBuf, null, mngMethodsBuf);
			String aop = toClassSource(implPkgName, aopImportMap.valueList(), aopClassBuf, null, aopMethodsBuf);
			String fc = toClassSource(pkgName, fcImportMap.valueList(), fcClassBuf, fcFieldsBuf, fcMethodsBuf);
			
			mappingList.addValue(new StringBuffer(StringUtils.replace(pkgName, ".", "/")).append("/hbm.xml").toString());

			if (getBoolean(options, OPTION_JAVASOURCE)) {
				Myjung.writeFileString(new StringBuffer(pkgPath).append("/").append(exception).append(".java").toString(), exceptionSource, true);
				Myjung.writeFileString(new StringBuffer(pkgPath).append("/").append(idaoName).append(".java").toString(), idao, true);
				Myjung.writeFileString(new StringBuffer(pkgPath).append("/impl/").append(daoName).append(".java").toString(), dao, true);
				Myjung.writeFileString(new StringBuffer(pkgPath).append("/").append("hbm.xml").toString(), hbm.toXMLString(), true);
				Myjung.writeFileString(new StringBuffer(pkgPath).append("/").append(imngName).append(".java").toString(), imng, true);
				Myjung.writeFileString(new StringBuffer(pkgPath).append("/impl/").append(mngName).append(".java").toString(), mng, true);
				Myjung.writeFileString(new StringBuffer(pkgPath).append("/").append(fcSimpleName).append(".java").toString(), fc, true);
				if (getBoolean(options, OPTION_AOPENABLED))
					Myjung.writeFileString(new StringBuffer(pkgPath).append("/impl/").append(aopName).append(".java").toString(), aop, true);
			}
			if (getBoolean(options, OPTION_WEBSOURCE) && getBoolean(options, OPTION_ADMINENABLED))
				Myjung.writeFileString(new StringBuffer(path).append(webappPath).append("/admin/model/").append(lowerGroupPrefix).append("/submenu.jsp").toString(),
						adminSubMenuBuf.toString(), true);
		}
	}
	
	private static void populateObjField(StringBuffer buf, FieldInfo fieldInfo, ClassInfo classInfo, Map<String,ClassInfo> classInfoMap, Map<String,MdlPackage> pkgMap) {
		String name = toParameter(fieldInfo.getName());
		MdlField field = fieldInfo.getField();
		String fieldType = Myjung.toString(field.getType(), "string");
		buf.append("\r\n\t\t\t<tr>");
		buf.append("\r\n\t\t\t\t<td class=\"label\">").append(fieldInfo.getName()).append("</td>");
		buf.append("\r\n\t\t\t\t<td class=\"value\">");
		if (fieldType.equals("string") || fieldType.equals("text")) {
			String value = new StringBuffer("StringUtils.replace(Myjung.toNotNull(obj.").append(fieldInfo.getGetter()).append("()), \"&\", \"&amp;\")").toString();
			if (fieldType.equals("text")) {
				buf.append("\r\n\t\t\t\t\t<textarea name=\"").append(name).append("\" class=\"textArea\"><%=").append(value).append("%></textarea>");
			} else if (field.getLength() != null && field.getLength() > 100) {
				buf.append("\r\n\t\t\t\t\t<textarea name=\"").append(name).append("\" class=\"textInputLong\"><%=").append(value).append("%></textarea>");
			} else {
				buf.append("\r\n\t\t\t\t\t<input name=\"").append(name).append("\" class=\"textInput\" value=\"<%=").append(value).append("%>\"/>");
			}
		} else if (fieldType.startsWith("id")) {
			buf.append("\r\n\t\t\t\t\t<input name=\"id\" class=\"textInput\" value=\"<%=Myjung.toNotNull(id)%>\"/>");
		} else if (fieldType.equals("creator") || fieldType.equals("modifier")) {
			buf.append("\r\n\t\t\t\t\t<%=Myjung.toNotNull(obj.").append(fieldInfo.getGetter()).append("())%>");
		} else if (fieldType.equals("date") || fieldType.equals("creationDate") || fieldType.equals("modificationDate")) {
			String value = new StringBuffer("Myjung.toNotNull(Myjung.toXsdDateTimeString(obj.").append(fieldInfo.getGetter()).append("()))").toString();
			if (fieldType.equals("date")) {
				buf.append("\r\n\t\t\t\t\t<input name=\"").append(name).append("\" class=\"textInput\" value=\"<%=").append(value).append("%>\"/>");
			} else {
				buf.append("\r\n\t\t\t\t\t<%=").append(value).append("%>");
			}
		} else if (fieldType.equals("boolean") || fieldType.equals("int") || fieldType.equals("long") || fieldType.equals("float") || fieldType.equals("double")) {
			String value = new StringBuffer("obj.").append(fieldInfo.getGetter()).append("() == null? \"\" : obj.").append(fieldInfo.getGetter()).append("().toString()").toString();
			buf.append("\r\n\t\t\t\t\t<input name=\"").append(name).append("\" class=\"textInput\" value=\"<%=").append(value).append("%>\"/>");
		} else if (fieldType.indexOf(".") != -1) {
			if (classInfoMap.containsKey(fieldType)) {
				ClassInfo fClassInfo = classInfoMap.get(fieldType);
				populate(fClassInfo, classInfoMap);
				FieldInfo fId = fClassInfo.getId();
				FieldInfo fTitle = fClassInfo.getTitle();
				buf.append("\r\n\t\t\t\t\t<%if (obj.").append(fieldInfo.getGetter()).append("() != null) {%>");
				if (fId != null && fTitle != null) {
					buf.append("\r\n\t\t\t\t\t<a class=\"valueRef\" onclick=\"Admin.getObj('")
							.append(toLowerGroupPrefix(pkgMap, fClassInfo.getPkg())).append("', '")
							.append(Myjung.toLowerCase(fClassInfo.getClazz().getName(), 0)).append("', '<%=obj.").append(fieldInfo.getGetter()).append("().").append(fId.getGetter()).append("()%>')\">");
					buf.append("\r\n\t\t\t\t\t\t<%=Myjung.toString(obj.").append(fieldInfo.getGetter()).append("().").append(fTitle.getGetter())
							.append("(), obj.").append(fieldInfo.getGetter()).append("().").append(fId.getGetter()).append("().toString())%>");
					buf.append("\r\n\t\t\t\t\t</a>");
				}
				buf.append("\r\n\t\t\t\t\t<%}%>");
				buf.append("\r\n\t\t\t\t\t<input type=\"button\" class=\"valueRefButton\" value=\"ref...\" disabled=\"disabled\"/>");
			}
		} else {
			
		}
		buf.append("\r\n\t\t\t\t</td>");
		buf.append("\r\n\t\t\t</tr>");
	}
	private static String toParameter(String name) {
		if (name.equals("method") || name.equals("menu") || name.equals("submenu") || 
				name.equals("formId") || name.equals("_parentId") || name.equals("id") || name.equals("type") || 
				name.equals("conds") || name.equals("pageNo") || name.equals("pageSize")) {
			return "_" + name;
		}
		return name;
	}
	
	private static void populate(ClassInfo classInfo, Map<String,ClassInfo> classInfoMap) {
		if (classInfo == null || classInfo.isPopulated())
			return;
		
		String extendz = classInfo.getExtendz();
		if (Myjung.isEmpty(extendz) || !classInfoMap.containsKey(extendz)) {
			classInfo.setPopulated(true);
			return;
		}
		ClassInfo parent = classInfoMap.get(extendz);
		if (!parent.isPopulated())
			populate(parent, classInfoMap);
		
		if (classInfo.getId() == null)
			classInfo.setId(parent.getId());
		if (classInfo.getTitle() == null)
			classInfo.setTitle(parent.getTitle());
		if (classInfo.getCreator() == null)
			classInfo.setCreator(parent.getCreator());
		if (classInfo.getCreated() == null)
			classInfo.setCreated(parent.getCreated());
		if (classInfo.getModifier() == null)
			classInfo.setModifier(parent.getModifier());
		if (classInfo.getModified() == null)
			classInfo.setModified(parent.getModified());
		
		classInfo.getFieldInfoMap().putAll(parent.getFieldInfoMap(), 0);
		classInfo.setPopulated(true);
	}
	
	private static String generateJsp(ListMap<String,String> importMap, String src) {
		StringBuffer buf = new StringBuffer("<%@page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>");
		List<String> importClasses = importMap.valueList();
		SortedSet<String> importClassSet = new TreeSet<String>(importClasses);
		if (!Myjung.isEmpty(importClassSet)) {
			for (String importClass : importClassSet)
				buf.append("\r\n<%@page import=\"").append(importClass).append("\"%>");
		}
		buf.append("\r\n<%@include file=\"/admin/common/include/default4Html.jsp\"%>");
		if (!Myjung.isEmpty(src))
			buf.append("\r\n").append(src);
		return buf.toString();
	}

	private static void appendHibernateProperties(String parent, 
			HbnClass hbClass, String pkgName, String lowerPrefix,
			String className, String tableName, MdlClass clazz,
			Map<String,MdlPackage> pkgMap, Map<String,Integer> indexMap, 
			Map<String,Map<String,String>> classFieldColumnMap, Map<String,String> classExtendsMap) {

		if (!Myjung.isEmpty(clazz.getExtends())) {
			String exts = clazz.getExtends();
			if (exts.equals(CN_BASEOBJECT)) {
//				return classInfo;
			} else if (exts.equals("MyObject") || exts.equals(CN_MYOBJECT)) {
				appendHibernateProperties(null, 
						hbClass, pkgName, lowerPrefix, className,
						tableName, myobject, pkgMap,
						indexMap, classFieldColumnMap, classExtendsMap);
			} else {
				String extsPkgName = toPackageName(exts);
				if (pkgMap.containsKey(extsPkgName)) {
					String extSimpleName = toSimpleName(exts);
					MdlPackage extsPkg = pkgMap.get(extsPkgName);
					List<MdlClass> extClasses = extsPkg.getClasses();
					if (!Myjung.isEmpty(extClasses)) {
						for (MdlClass extClass : extClasses) {
							if (!extClass.getName().equals(extSimpleName))
								continue;
							appendHibernateProperties(null, 
									hbClass, pkgName,
									lowerPrefix, className, tableName,
									extClass, pkgMap,
									indexMap, classFieldColumnMap, classExtendsMap);
							break;
						}
					}
				}
			}
		}
		
		List<MdlField> fields = clazz.getFields();
		if (Myjung.isEmpty(fields))
			return;

		List<MdlField> cols = null;
		String ixPrefix = new StringBuffer("Ix").append(tableName).toString();
		int ixIndex = indexMap.containsKey("ixIndex") ? indexMap.get("ixIndex") : 0;
		String fkPrefix = new StringBuffer("Fk").append(tableName).toString();
		int fkIndex = indexMap.containsKey("fkIndex") ? indexMap.get("fkIndex") : 0;
		for (MdlField field : fields) {
			if ("disabled".equals(field.getColumn()))
				continue;

			String type = Myjung.toString(field.getType(), "string");
			if (type.equals("MyObject"))
				type = CN_MYOBJECT;
			String multi = field.getMultiplicity();

			if (!type.startsWith("id") && "*".equals(multi)) {
				if (cols == null)
					cols = new ArrayList<MdlField>();
				cols.add(field);
				continue;
			}

			String fieldName = toGetterSetterName(field.getName());
			String columnName = toDbColumnName(lowerPrefix, field);
			field.setColumn(columnName);

			if (type.indexOf(".") != -1) {
				HbnMany_to_one manyToOne = new HbnMany_to_one();
				manyToOne.setName(fieldName);
				if (!fieldName.equals(columnName))
					manyToOne.setColumn(columnName);
				manyToOne.setForeign_key(new StringBuffer(fkPrefix).append(fkIndex++).toString());
				manyToOne.setNot_found("ignore");
				String cascade = Myjung.toBoolean(field.getReference())? "none" : "all";
				manyToOne.setCascade(cascade);
				hbClass.addMany_to_one(manyToOne);
			} else {
				HbnProperty prop = null;

				if (type.startsWith("id")) {
					HbnId id = new HbnId();
					prop = id;
					HbnGenerator idGen = new HbnGenerator();
					if (type.equals("id")) {
						idGen.setClazz(CN_IDGENERATOR);
						id.setUnsaved_value("undefined");
						prop.setType("string");
						prop.setLength(Myjung.toString(field.getLength() == null ? null : field.getLength().toString(), "50"));
					} else if (type.equals("idInt")) {
						idGen.setClazz("identity");
						prop.setType("int");
					} else if (type.equals("idLong")) {
						idGen.setClazz("identity");
						prop.setType("long");
					}
					id.setGenerator(idGen);
					hbClass.setId(id);
				} else {
					prop = new HbnProperty();
					if (type.equals("string") || type.equals("creator") || type.equals("modifier")) {
						prop.setType("string");
						prop.setLength(Myjung.toString(field.getLength() == null ? null : field.getLength().toString(), "50"));
					} else if (type.equals("date") || type.equals("creationDate") || type.equals("modificationDate")) {
						prop.setType("timestamp");
					} else {
						prop.setType(type);
					}
					if (!type.equals("text")
							&& !Myjung.isEmpty(field.getIndex())) {
						String index = field.getIndex();
						prop.setIndex(index.equals("enabled") ? new StringBuffer(ixPrefix).append(ixIndex++).toString() : index);
					}
					hbClass.addProperty(prop);
				}

				prop.setName(fieldName);
				if (!fieldName.equals(columnName))
					prop.setColumn(columnName);
			}
		}
		
		if (!Myjung.isEmpty(parent)) {
			HbnMany_to_one parentRel = new HbnMany_to_one();
			parentRel.setName("_parent");
			parentRel.setColumn(toId(lowerPrefix, "_parentId"));
			parentRel.setForeign_key(new StringBuffer("Fk").append(
					hbClass.getName()).append("PId").toString());
			parentRel.setClazz(parent);
			parentRel.setCascade("none");
			parentRel.setNot_found("ignore");
			hbClass.addMany_to_one(parentRel);
		}
		
		if (cols != null) {
			String listIndexName = toId(lowerPrefix, "listIndex");
			for (MdlField field : cols) {
				String type = Myjung.toString(field.getType(), "string");
				if (type.equals("MyObject"))
					type = CN_MYOBJECT;

				HbnCollection col = null;
				if (Myjung.isEmpty(field.getOrderBy())) {
					HbnList list = new HbnList();
					HbnList_index listIndex = new HbnList_index();
					listIndex.setColumn(type.equals(className) ? listIndexName
							+ "Self" : listIndexName);
					list.setList_index(listIndex);
					hbClass.addList(list);
					col = list;
				} else {
					HbnSet set = new HbnSet();
					String orderBy = field.getOrderBy();
					String[] commaTokens = StringUtils.tokenizeToStringArray(orderBy, ",");
					StringBuffer orderByBuf = new StringBuffer();
					int i = 0;
					for (String commaToken : commaTokens) {
						if (i++ != 0)
							orderByBuf.append(", ");
						String[] tokens = StringUtils.tokenizeToStringArray(commaToken, " ");
						orderByBuf.append(toFieldName(type, tokens[0], classFieldColumnMap, classExtendsMap));
						if (tokens.length > 1)
							orderByBuf.append(" ").append(tokens[1]);
					}
					set.setOrder_by(orderByBuf.toString());
					hbClass.addSet(set);
					col = set;
				}

				String fieldName = toGetterSetterName(field.getName());
				String pluralFieldName = toFieldName(toPlural(field));
				col.setName(Myjung.isEmpty(pluralFieldName) || pluralFieldName.equals("none") ? fieldName : pluralFieldName);

				HbnKey key = new HbnKey();
				key.setColumn(new StringBuffer(lowerPrefix).append("_parentId").toString());
				key.setForeign_key(new StringBuffer(fkPrefix).append(fkIndex++).toString());
				col.setKey(key);
				col.setCascade("all");
				// primitive 유형의 컬렉션 타입인 경우
				if (type.indexOf(".") == -1) {
					col.setTable(new StringBuffer(tableName).append(Myjung.isEmpty(field.getColumn()) ? fieldName : field.getColumn()).toString());
					HbnElement elem = new HbnElement();
					elem.setName(fieldName);
					String columnName = toDbColumnName(lowerPrefix, field);
					if (!fieldName.equals(columnName))
						elem.setColumn(columnName);
					if (col instanceof HbnList)
						((HbnList) col).setElement(elem);
					else if (col instanceof HbnSet)
						((HbnSet) col).setElement(elem);
				} else {
					HbnOne_to_many oneToMany = new HbnOne_to_many();
					type = toJavaType(type, pkgMap);
					if (pkgName.equals(toPackageName(type)))
						type = toSimpleName(type);
					oneToMany.setClazz(type);
					oneToMany.setNot_found("ignore");
					if (col instanceof HbnList)
						((HbnList) col).setOne_to_many(oneToMany);
					else if (col instanceof HbnSet)
						((HbnSet) col).setOne_to_many(oneToMany);
				}
			}
		}
		indexMap.put("ixIndex", ixIndex);
		indexMap.put("fkIndex", fkIndex);
	}
	private static String toFieldName(String type, String name, Map<String,Map<String,String>> classFieldColumnMap, Map<String,String> classExtendsMap) {
		if (Myjung.isEmpty(type) || !classFieldColumnMap.containsKey(type))
			return name;
		Map<String,String> fieldColumnMap = classFieldColumnMap.get(type);
		if (fieldColumnMap.containsKey(name))
			return fieldColumnMap.get(name);
		return classExtendsMap.containsKey(type)? toFieldName(classExtendsMap.get(type), name, classFieldColumnMap, classExtendsMap) : name;
	}

	private void appendManagerBean(SprBeans beans, String prefix,
			String pkgName, String managerName, String interceptorName, String extInterceptorBeanId, 
			Map<String,Object> options) {
		String id = Myjung.toLowerCase(managerName, 0);
		String targetId = new StringBuffer(id).append(SF_TARGET).toString();
		String advId = new StringBuffer(id).append(SF_INTERCEPTOR).toString();

		// manager bean
		SprBean bean = new SprBean();
		bean.setId(id);
		bean.setClazz(CN_PROXYFACTORYBEAN);

		SprProperty targetProp = new SprProperty();
		targetProp.setName("target");
		targetProp.setRef(targetId);
		bean.addProperty(targetProp);

		SprProperty advNamesProp = new SprProperty();
		advNamesProp.setName("interceptorNames");
		SprList advList = new SprList();
		/* value */
		advList.addValue(toId(prefix, "loggingInterceptor"));
		/* value */
		advList.addValue(toId(prefix, "transactionInterceptor"));
		if (!Myjung.isEmpty(extInterceptorBeanId))
			advList.addValue(extInterceptorBeanId);
		if (getBoolean(options, OPTION_AOPENABLED))
			advList.addValue(advId);
		advNamesProp.setList(advList);
		bean.addProperty(advNamesProp);

		// target bean
		SprBean targetBean = new SprBean();
		targetBean.setClazz(new StringBuffer(pkgName).append(".impl.").append(
				managerName).toString());
		targetBean.setId(targetId);
		SprProperty sfProp = new SprProperty();
		sfProp.setName("sessionFactory");
		/* value */
		sfProp.setRef(toId(prefix, "sessionFactory"));
		targetBean.addProperty(sfProp);

		// interceptor bean
		SprBean advBean = null;
		if (getBoolean(options, OPTION_AOPENABLED)) {
			advBean = new SprBean();
			advBean.setId(advId);
			advBean.setClazz(new StringBuffer(pkgName).append(".impl.").append(
					interceptorName).toString());
		}

		beans.addBean(bean);
		beans.addBean(targetBean);
		if (getBoolean(options, OPTION_AOPENABLED))
			beans.addBean(advBean);
	}

	private static void appendInterceptor(StringBuffer buf, String prefix,
			String objName, String suffix, String paramsClassName,
			MdlImplementation impl, Map<String, String> importMap) {
		prefix = prefix == null ? "" : prefix;
		suffix = suffix == null ? "" : suffix;
		String ann = impl == null || Myjung.isEmpty(impl.getSource()) ? "//" : "";
		paramsClassName = addImportClassName(importMap, paramsClassName);
		buf.append("\r\n").append(ann).append("\tpublic void ").append(prefix).append(objName).append(suffix);
		buf.append("(").append(paramsClassName).append(" params) throws Exception {\r\n");
		appendImplementation(buf, ann, impl, importMap, false);
		buf.append("\r\n").append(ann).append("\t}");
	}

	private static void appendImplementation(StringBuffer buf, String ann,
			MdlImplementation impl, Map<String, String> importMap, boolean hasReturn) {
		ann = ann == null ? "" : ann;
		String source = null;
		if (impl != null) {
			List<String> imports = impl.getImports();
			source = impl.getSource();
			if (!Myjung.isEmpty(imports)) {
				for (String ipt : imports)
					addImportClassName(importMap, ipt);
			}
		}
		if (!Myjung.isEmpty(source)) {
			buf.append(toSource(source, "\t\t", ann));
		} else {
			buf.append(ann).append("\t\t// TODO");
			if (hasReturn)
				buf.append("\r\n").append(ann).append("\t\treturn null;");
		}
	}

	private void generateModels(MdlPackage pkg, String path, String javaPath, 
			Map<String,ClassInfo> classInfoMap, Map<String,MdlPackage> pkgMap, Map<String,Object> options, 
			Map<String,String> childParentMap, Map<String,Map<String,String>> classFieldColumnMap, Map<String,String> classExtendsMap)
			throws Exception {
		if (Myjung.isEmpty(pkg.getClasses()))
			return;
		String pkgPath = toPackagePath(path, javaPath, pkg.getName());
		for (MdlClass clazz : pkg.getClasses()) {
			if (!clazz.getModelEnabled())
				continue;
			options.put(OPTION_MODELENABLED, true);
			String source = generateModel(clazz, pkg, classInfoMap, pkgMap, childParentMap, classFieldColumnMap, classExtendsMap);
			
			if (getBoolean(options, OPTION_JAVASOURCE)) {
				String srcPath = new StringBuffer(pkgPath).append("/").append(getPrefix(pkg)).append(toValidName(clazz.getName())).append(".java").toString();
				Myjung.writeFileString(srcPath, source, true);
			}
		}
	}

	private static void populateField(FieldInfo field, StringBuffer fieldsBuf, StringBuffer methodsBuf, Map<String,String> importMap) {
		String name = field.getName();
		String type = field.getType();
		type = addImportClassName(importMap, type);
		String generic = field.getGeneric();
		if (!Myjung.isEmpty(generic)) {
			generic = addImportClassName(importMap, generic);
			type = new StringBuffer(type).append("<").append(generic).append(">").toString();
		}
		String getter = field.getGetter();
		String setter = field.getSetter();
		String adder = field.getAdder();
		String remover = field.getRemover();
		
		fieldsBuf.append("\r\n\tprivate ").append(type).append(" ").append(name).append(";");
		if (!Myjung.isEmpty(getter)) {
			methodsBuf.append("\r\n\tpublic ").append(type).append(" ").append(getter).append("() {");
			methodsBuf.append("\r\n\t\treturn ").append(name).append(";");
			methodsBuf.append("\r\n\t}");
		}
		if (!Myjung.isEmpty(setter)) {
			methodsBuf.append("\r\n\tpublic void ").append(setter).append("(").append(type).append(" ").append(name).append(") {");
			methodsBuf.append("\r\n\t\tthis.").append(name).append(" = ").append(name).append(";");
			methodsBuf.append("\r\n\t}");
		}
		if (Myjung.isEmpty(generic))
			return;
		String singular = Myjung.toString(field.getSingular(), name);
		if (!Myjung.isEmpty(adder)) {
			methodsBuf.append("\r\n\tpublic void ").append(adder).append("(").append(generic).append(" ").append(singular).append(") {");
			methodsBuf.append("\r\n\t\tif (this.").append(name).append(" == null)");
			methodsBuf.append("\r\n\t\t\tthis.").append(name) .append(" = new ")
						.append(type.indexOf("Set") == -1? addImportClassName(importMap, CN_ARRAYLIST) : addImportClassName(importMap, CN_HASHSET))
						.append("<").append(generic).append(">();");
			methodsBuf.append("\r\n\t\tthis.").append(name).append(".add(").append(singular).append(");");
			methodsBuf.append("\r\n\t}");
		}
		if (!Myjung.isEmpty(remover)) {
			methodsBuf.append("\r\n\tpublic void ").append(remover).append("(").append(generic).append(" ").append(singular).append(") {");
			methodsBuf.append("\r\n\t\tif (this.").append(name).append(" == null || !this.").append(name).append(".contains(").append(singular).append("))");
			methodsBuf.append("\r\n\t\t\treturn;");
			methodsBuf.append("\r\n\t\tthis.").append(name).append(".remove(").append(singular).append(");");
			methodsBuf.append("\r\n\t}");
		}
	}
	private static String generateModel(MdlClass clazz, MdlPackage pkg, Map<String,ClassInfo> classInfoMap, Map<String,MdlPackage> pkgMap, 
			Map<String,String> childParentMap, Map<String,Map<String,String>> classFieldColumnMap, Map<String,String> classExtendsMap) 
			throws Exception {
		ClassInfo classInfo = new ClassInfo();
		classInfo.setClazz(clazz);
		
		ListMap<String, String> importMap = new ListMap<String, String>();
		StringBuffer classBuf = new StringBuffer();
		StringBuffer fieldsBuf = new StringBuffer();
		StringBuffer constrBuf = new StringBuffer();
		StringBuffer methodsBuf = new StringBuffer();

		String pkgName = pkg.getName();
		classInfo.setPkg(pkgName);
		String extendz = toJavaType(Myjung.isEmpty(clazz.getExtends()) ? CN_BASEOBJECT : clazz.getExtends(), pkgMap);
		classInfo.setExtendz(extendz);
		extendz = addImportClassName(importMap, extendz);
		
		String prefix = getPrefix(pkg);
		String lowerPrefix = Myjung.isEmpty(prefix)? "" : Myjung.toLowerCase(prefix, 0);
		String modelSimpleName = clazz.getName();
		String modelClassName = new StringBuffer(pkgName).append(".").append(modelSimpleName).toString();
		classFieldColumnMap.put(modelClassName, new HashMap<String,String>());
		if (!Myjung.isEmpty(clazz.getExtends()))
			classExtendsMap.put(modelClassName, clazz.getExtends());
		String simpleName = toValidName(modelSimpleName);
		String dtd = clazz.getDtd();
		boolean hasName = !simpleName.equals(modelSimpleName);
		boolean hasPrefix = !Myjung.isEmpty(prefix);
		boolean hasDtd = !Myjung.isEmpty(dtd);
		simpleName = new StringBuffer(prefix).append(simpleName).toString();
		classInfo.setName(simpleName);
		classBuf.append("@").append(addImportClassName(importMap, AN_MDLCLASS));
		if (hasName || hasPrefix || hasDtd) {
			classBuf.append("(");
			int annIndex = 0;
			if (hasName || hasPrefix)
				classBuf.append(annIndex++ > 0 ? ", " : "").append("name = \"").append(modelSimpleName).append("\"");
			if (hasDtd)
				classBuf.append(annIndex++ > 0 ? ", " : "").append("dtd = \"").append(StringUtils.replace(dtd, "\"", "\\\"")).append("\"");
			classBuf.append(")");
		}
		classBuf.append("\r\n@SuppressWarnings(\"serial\")");
		classBuf.append("\r\npublic class ").append(simpleName);
		classBuf.append(" extends ").append(extendz);
		
		// _parent
		String parentSimpleName = childParentMap.containsKey(modelClassName)? 
				new StringBuffer(prefix).append(toValidName(childParentMap.get(modelClassName))).toString() : null;
		if (parentSimpleName != null) {
			FieldInfo parent = new FieldInfo();
			parent.setName("_parent");
			parent.setGetter("get_parent");
			parent.setSetter("set_parent");
			parent.setType(new StringBuffer(pkgName).append(".").append(parentSimpleName).toString());
			fieldsBuf.append("\t@").append(addImportClassName(importMap, AN_MDLFIELD));
			fieldsBuf.append("(type = \"").append(parent.getType()).append("\")");
			populateField(parent, fieldsBuf, methodsBuf, importMap);
			classInfo.setParent(parent);
		}
		
		List<MdlField> fields = clazz.getFields();
		if (!Myjung.isEmpty(fields)) {
			for (MdlField field : fields) {
				String name = field.getName();
				classFieldColumnMap.get(modelClassName).put(name, toDbColumnName(lowerPrefix, field));
				String singular = null;
				String type = toJavaType(field.getType(), pkgMap);
				String fieldName = toFieldName(name);
				boolean collection = "*".equals(field.getMultiplicity());
				String plural = collection ? toPlural(field) : null;
				String defaultValue = field.getDefaultValue();
				if (!collection && !Myjung.isEmpty(defaultValue)) {
					if (constrBuf.length() == 0)
						constrBuf.append("\r\n\tpublic ").append(simpleName).append("() {\r\n\t\tsuper();");
					if (CN_STRING.equals(type)) {
						String tmp = StringUtils.replace(defaultValue, "\\", "<rep:\\>");
						if (tmp.indexOf("\r") == -1 && tmp.indexOf("\n") == -1) {
							constrBuf.append("\r\n\t\t").append(fieldName).append(" = \"").append(defaultValue).append("\";");
						} else {
							tmp = StringUtils.replace(tmp, "\r\n", "<rep:rn>");
							tmp = StringUtils.replace(tmp, "\r", "<rep:rn>");
							tmp = StringUtils.replace(tmp, "\n", "<rep:rn>");
							tmp = StringUtils.replace(tmp, "<rep:\\>", "\\");
							String[] values = tmp.split("<rep:rn>");
							if (constrBuf.indexOf("StringBuffer _buf = ") == -1)
								constrBuf.append("\r\n\t\tStringBuffer _buf = new StringBuffer();");
							else
								constrBuf.append("\r\n\t\t_buf = new StringBuffer();");
							int i = 0;
							for (String value : values)
								constrBuf.append("\r\n\t\t_buf.append(\"").append(i++ == 0? "" : "\\r\\n").append(value).append("\");");
							constrBuf.append("\r\n\t\t").append(fieldName).append(" = _buf.toString();");
						}
					} else if (CN_BOOLEAN.equals(type)) {
						String myjung = addImportClassName(importMap, CN_MYJUNG);
						constrBuf.append("\r\n\t\t").append(fieldName).append(" = ").append(myjung).append(".toBoolean(\"").append(defaultValue.trim()).append("\");");
					} else if (CN_DATE.equals(type)) {
						String myjung = addImportClassName(importMap, CN_MYJUNG);
						constrBuf.append("\r\n\t\t").append(fieldName).append(" = ").append(myjung).append(".toDate(\"").append(defaultValue.trim()).append("\");");
					} else if (CN_INTEGER.equals(type)) {
						constrBuf.append("\r\n\t\t").append(fieldName).append(" = Integer.parseInt(\"").append(defaultValue.trim()).append("\");");
					} else if (CN_LONG.equals(type)) {
						constrBuf.append("\r\n\t\t").append(fieldName).append(" = Long.parseLong(\"").append(defaultValue.trim()).append("\");");
					} else if (CN_FLOAT.equals(type)) {
						constrBuf.append("\r\n\t\t").append(fieldName).append(" = Float.parseFloat(\"").append(defaultValue.trim()).append("\");");
					} else if (CN_DOUBLE.equals(type)) {
						constrBuf.append("\r\n\t\t").append(fieldName).append(" = Double.parseDouble(\"").append(defaultValue.trim()).append("\");");
					}
				}
				int annIndex = 0;
				if (fieldsBuf.length() > 0)
					fieldsBuf.append("\r\n");
				if (field instanceof MdlAttribute) {
					fieldsBuf.append("\t@").append(addImportClassName(importMap, AN_MDLATTRIBUTE));
					fieldsBuf.append("(");
					if (!name.equals(fieldName))
						fieldsBuf.append(annIndex++ > 0 ? ", " : "").append("name = \"").append(name).append("\"");
				} else if (field instanceof MdlText) {
					fieldsBuf.append("\t@").append(addImportClassName(importMap, AN_MDLTEXT));
					fieldsBuf.append("(");
				} else {
					if (field instanceof MdlElement)
						fieldsBuf.append("\t@").append(addImportClassName(importMap, AN_MDLELEMENT));
					else
						fieldsBuf.append("\t@").append(addImportClassName(importMap, AN_MDLFIELD));
					fieldsBuf.append("(");
					if (collection) {
						if (plural.equals("none")) {
							if (!name.equals(fieldName))
								fieldsBuf.append(annIndex++ > 0 ? ", " : "").append("name = \"").append(name).append("\"");
						} else {
							fieldName = toFieldName(plural);
							singular = name;
							name = plural;
							if (!fieldName.equals(name))
								fieldsBuf.append(annIndex++ > 0 ? ", " : "").append("name = \"").append(name).append("\"");
							fieldsBuf.append(annIndex++ > 0 ? ", " : "").append("singular = \"").append(singular).append("\"");
						}
						fieldsBuf.append(annIndex++ > 0 ? ", " : "").append("generic = \"").append(type).append("\"");
					} else if (!name.equals(fieldName)) {
						fieldsBuf.append(annIndex++ > 0 ? ", " : "").append("name = \"").append(name).append("\"");
					}
				}
				if (!Myjung.isEmpty(field.getColumn()))
					fieldsBuf.append(annIndex++ > 0 ? ", " : "").append("column = \"").append(field.getColumn()).append("\"");
				fieldsBuf.append(annIndex++ > 0 ? ", " : "").append("type = \"").append(Myjung.toString(field.getType(), "string")).append("\")");

				name = toGetterSetterUpperName(name);
				FieldInfo fieldInfo = new FieldInfo();
				fieldInfo.setName(fieldName);
				fieldInfo.setField(field);
				fieldInfo.setGetter(new StringBuffer("get").append(name).toString());
				fieldInfo.setSetter(new StringBuffer("set").append(name).toString());
				if (collection) {
					fieldInfo.setType(Myjung.isEmpty(field.getOrderBy())? CN_LIST : CN_SET);
					fieldInfo.setGeneric(type);
					fieldInfo.setSingular(toFieldName(singular));
					name = singular == null ? name : toGetterSetterUpperName(singular);
					fieldInfo.setAdder(new StringBuffer("add").append(name).toString());
					fieldInfo.setRemover(new StringBuffer("remove").append(name).toString());
				} else {
					fieldInfo.setType(type);
				}
				populateField(fieldInfo, fieldsBuf, methodsBuf, importMap);
				classInfo.setFieldInfo(field.getName(), fieldInfo);
				String modelType = field.getType();
				if (Myjung.isEmpty(modelType) || modelType.equals("string")) {
					
				} else if (modelType.startsWith("id")) {
					classInfo.setId(fieldInfo);
				} else if (modelType.equals("creator")) {
					classInfo.setCreator(fieldInfo);
				} else if (modelType.equals("creationDate")) {
					classInfo.setCreated(fieldInfo);
				} else if (modelType.equals("modifier")) {
					classInfo.setModifier(fieldInfo);
				} else if (modelType.equals("modificationDate")) {
					classInfo.setModified(fieldInfo);
				}
			}
			if (constrBuf.length() > 0) {
				constrBuf.append("\r\n\t}\r\n");
				methodsBuf = constrBuf.append(methodsBuf);
			}
			if (!Myjung.isEmpty(clazz.getTitleField()))
				classInfo.setTitle(classInfo.getFieldInfo(clazz.getTitleField()));
		}
		
		classInfoMap.put(new StringBuffer(classInfo.getPkg()).append(".").append(classInfo.getName()).toString(), classInfo);

		return toClassSource(pkgName, importMap.valueList(), classBuf, fieldsBuf, methodsBuf);
	}

	private static String addImportClassName(
			Map<String, String> importClassMap, String className) {
		className = toValidName(className);
		String simpleName = toSimpleName(className);
		if (!importClassMap.containsKey(simpleName)) {
			if (!className.startsWith("java.lang."))
				importClassMap.put(simpleName, className);
		} else if (!importClassMap.get(simpleName).equals(className)) {
			return className;
		}
		return simpleName;
	}

	private static String toObjName(String modelClassName) {
		return toValidName(toSimpleName(modelClassName));
	}
	private static String toDbColumnName(String prefix, MdlField field) {
		return Myjung.isEmpty(field.getColumn()) ? toId(prefix, toGetterSetterName(field.getName())) : field.getColumn();
	}
	private static String toJavaType(String modelType,
			Map<String, MdlPackage> pkgMap) {
		if (Myjung.isEmpty(modelType))
			return CN_STRING;
		if (modelType.indexOf(".") != -1) {
			String pkgName = toPackageName(modelType);
			if (!pkgMap.containsKey(pkgName))
				return modelType;
			MdlPackage pkg = pkgMap.get(pkgName);
			if (Myjung.isEmpty(pkg.getPrefix()))
				return modelType;
			return new StringBuffer(pkgName).append(".").append(getPrefix(pkg)).append(toSimpleName(modelType)).toString();
		}
		if (modelType.equals("boolean"))
			return CN_BOOLEAN;
		else if (modelType.equals("date") || modelType.equals("creationDate") || modelType.equals("modificationDate"))
			return CN_DATE;
		else if (modelType.equals("creator") || modelType.equals("modifier")
				|| modelType.equals("id") || modelType.equals("string")
				|| modelType.equals("text"))
			return CN_STRING;
		else if (modelType.equals("int") || modelType.equals("idInt"))
			return CN_INTEGER;
		else if (modelType.equals("long") || modelType.equals("idLong"))
			return CN_LONG;
		else if (modelType.equals("float"))
			return CN_FLOAT;
		else if (modelType.equals("double"))
			return CN_DOUBLE;
		else if (modelType.equals("BaseObject"))
			return CN_BASEOBJECT;
		else if (modelType.equals("MyObject"))
			return CN_MYOBJECT;
		else if (modelType.equals("List"))
			return CN_LIST;
		else if (modelType.equals("Map"))
			return CN_MAP;
		else if (modelType.equals("Object"))
			return CN_OBJECT;
		return modelType;
	}
	private static String toPlural(MdlField field) {
		String plural = field.getPlural();
		if (!Myjung.isEmpty(plural) && !plural.equals("auto"))
			return plural;
		String name = field.getName();
		if (name.equals("child"))
			return "children";
		else if (name.equals("person"))
			return "people";
		else if (name.endsWith("y"))
			return new StringBuffer(name.substring(0, name.length() - 1)).append("ies").toString();
		else if (name.endsWith("s") || name.endsWith("ch") || name.endsWith("sh"))
			return new StringBuffer(name).append("es").toString();
		return new StringBuffer(name).append("s").toString();
	}
	private static String toPrefix(MdlXmdl model) {
		return Myjung.isEmpty(model.getPrefix()) ? "" : Myjung.toLowerCase(model.getPrefix(), 0);
	}
	private static String getPrefix(MdlPackage pkg) {
		return Myjung.isEmpty(pkg.getPrefix()) ? "" : toValidName(Myjung.toUpperCase(pkg.getPrefix(), 0));
	}
	private static void setMyObject() {
		StringBuffer buf = new StringBuffer();
		buf.append("<class name=\"MyObject\" titleField=\"name\">");
		buf.append("\r\n\t<attribute name=\"id\" type=\"id\"/>");
		buf.append("\r\n\t<attribute name=\"name\" length=\"100\" index=\"enabled\"/>");
		buf.append("\r\n\t<attribute name=\"creator\" type=\"creator\" index=\"enabled\"/>");
		buf.append("\r\n\t<attribute name=\"created\" type=\"creationDate\" index=\"enabled\"/>");
		buf.append("\r\n\t<attribute name=\"modifier\" type=\"modifier\" index=\"enabled\"/>");
		buf.append("\r\n\t<attribute name=\"modified\" type=\"modificationDate\" index=\"enabled\"/>");
		buf.append("\r\n\t<attribute name=\"status\" index=\"enabled\"/>");
		buf.append("\r\n\t<element name=\"description\" column=\"desc\" type=\"text\"/>");
		buf.append("\r\n</class>");
		myobject = (MdlClass) new MdlClass().toObject(buf.toString());
		myobjectInfo = new ClassInfo();
		myobjectInfo.setClazz(myobject);
		myobjectInfo.setPkg("net.myjung.model");
		myobjectInfo.setName("MyObject");
		FieldInfo id = new FieldInfo("id", CN_STRING, "getId", "setId");
		FieldInfo name = new FieldInfo("name", CN_STRING, "getName", "setName");
		FieldInfo creator = new FieldInfo("creator", CN_STRING, "getCreator", "setCreator");
		FieldInfo created = new FieldInfo("created", CN_DATE, "getCreated", "setCreated");
		FieldInfo modifier = new FieldInfo("modifier", CN_STRING, "getModifier", "setModifier");
		FieldInfo modified = new FieldInfo("modified", CN_DATE, "getModified", "setModified");
		FieldInfo status = new FieldInfo("status", CN_STRING, "getStatus", "setStatus");
		FieldInfo description = new FieldInfo("description", CN_STRING, "getDescription", "setDescription");
		myobjectInfo.setId(id);
		myobjectInfo.setTitle(name);
		myobjectInfo.setCreator(creator);
		myobjectInfo.setCreated(created);
		myobjectInfo.setModifier(modifier);
		myobjectInfo.setModified(modified);
		myobjectInfo.setFieldInfo("id", id);
		myobjectInfo.setFieldInfo("name", name);
		myobjectInfo.setFieldInfo("creator", creator);
		myobjectInfo.setFieldInfo("created", created);
		myobjectInfo.setFieldInfo("modifier", modifier);
		myobjectInfo.setFieldInfo("modified", modified);
		myobjectInfo.setFieldInfo("status", status);
		myobjectInfo.setFieldInfo("description", description);
		for (MdlField field : myobject.getFields()) {
			String fieldName = field.getName();
			if (fieldName.equals("id")) {
				id.setField(field);
			} else if (fieldName.equals("name")) {
				name.setField(field);
			} else if (fieldName.equals("creator")) {
				creator.setField(field);
			} else if (fieldName.equals("created")) {
				created.setField(field);
			} else if (fieldName.equals("modifier")) {
				modifier.setField(field);
			} else if (fieldName.equals("modified")) {
				modified.setField(field);
			} else if (fieldName.equals("status")) {
				status.setField(field);
			} else if (fieldName.equals("description")) {
				description.setField(field);
			}
		}
	}
	private static StringBuffer populateAdminSubMenu() {
		StringBuffer buf = new StringBuffer("<%@page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>");
		buf.append("\r\n<%@include file=\"/admin/common/include/default4Html.jsp\"%>");
		buf.append("\r\n<%");
		buf.append("\r\nString menu = Myjung.toNotNull(request.getParameter(\"menu\"));");
		buf.append("\r\nString submenu = Myjung.toNotNull(request.getParameter(\"submenu\"));");
		buf.append("\r\n%>");
		return buf;
	}
	private String newAdminDefaultJspSource(String username, String password) {
		StringBuffer buf = new StringBuffer("<%@page import=\"net.myjung.Myjung\"%>");
		buf.append("\r\n<%");
		buf.append("\r\nresponse.setDateHeader(\"Expires\", 0);");
		buf.append("\r\nresponse.setHeader(\"Pragma\", \"no-cache\");");
		buf.append("\r\nresponse.setHeader(\"Cache-Control\", request.getProtocol().equals(\"HTTP/1.1\")? \"no-cache\" : \"no-store\");");
		buf.append("\r\n");
		buf.append("\r\ntry {");
		buf.append("\r\n%>");
		buf.append(getAuthenticationSource(username, password));
		buf.append("\r\n<%");
		buf.append("\r\n} finally {");
		buf.append("\r\n}");
		buf.append("\r\n%>");
		buf.append("\r\n<%@include file=\"/admin/common/include/path.jsp\"%>");
		return buf.toString();
	}
	protected String getAuthenticationSource(String username, String password) {
		if (Myjung.isEmpty(username))
			return "";
		StringBuffer buf = new StringBuffer();
		buf.append("\r\n<%");
		buf.append("\r\nString username = (String) session.getAttribute(\"username\");");
		buf.append("\r\nString password = (String) session.getAttribute(\"password\");");
		buf.append("\r\nif (");
		if (!Myjung.isEmpty(username) || !Myjung.isEmpty(password))
			buf.append("username == null || !username.equals(\"").append(username).append("\")");
		if (!Myjung.isEmpty(username) && !Myjung.isEmpty(password))
			buf.append(" || ");
		if (!Myjung.isEmpty(password))
			buf.append("password == null || !password.equals(\"").append(password).append("\")");
		buf.append(") {");
		buf.append("\r\n\tusername = request.getParameter(\"username\");");
		buf.append("\r\n\tpassword = request.getParameter(\"password\");");
		buf.append("\r\n\tif (");
		buf.append("username != null && username.equals(\"").append(username).append("\")");
		if (!Myjung.isEmpty(username) && !Myjung.isEmpty(password))
			buf.append(" && ");
		if (!Myjung.isEmpty(password))
			buf.append("password != null && password.equals(\"").append(password).append("\")");
		buf.append(") {");
		buf.append("\r\n\t\tsession.setAttribute(\"username\", username);");
		buf.append("\r\n\t\tsession.setAttribute(\"password\", password);");
		buf.append("\r\n\t} else {");
		buf.append("\r\n\t\tresponse.sendRedirect(request.getContextPath() + \"/admin/login.jsp?username=\" + Myjung.toNotNull(username));");
		buf.append("\r\n\t}");
		buf.append("\r\n}");
		buf.append("\r\n%>");
		return buf.toString();
	}
	protected StringBuffer openAdminHeaderBuf() {
		StringBuffer buf = new StringBuffer("<%@page language=\"java\" contentType=\"text/html; charset=UTF-8\" pageEncoding=\"UTF-8\"%>");
		buf.append("\r\n<%@page import=\"net.myjung.Myjung\"%>");
		buf.append("\r\n<%@include file=\"/admin/common/include/path.jsp\"%>");
		buf.append("\r\n<%String menu = Myjung.toNotNull(request.getParameter(\"menu\"));%>");
		buf.append("\r\n<div id=\"header\">");
		buf.append("\r\n\t<div id=\"logoTitle\"><a href=\"<%=path%>/admin\">Administrator</a></div>");
		buf.append("\r\n\t<div id=\"headerMenu\"><a onclick=\"location.href = '<%=path%>/admin/login.jsp'\">logout</a></div>");
		buf.append("\r\n\t<div id=\"menu\">");
		return buf;
	}
	protected SprBeans newBeans(MdlXmdl model, SprList hbmList) {
		SprBeans beans = new SprBeans();
		
		populateBeans(beans, hbmList, toPrefix(model), model.getDataSource(), model.getTransaction());
		
		return beans;
	}
	protected void populateBeans(SprBeans beans, SprList hbmList, String prefix, MdlDataSource ds, MdlTransaction tx) {
		// DataSource/SessionFactory
		String dsBeanId = toId(prefix, "dataSource");

		SprBean dsBean = null;
		if (ds != null && !Myjung.isEmpty(ds.getType())) {
			String dsType = ds.getType();
			dsBean = new SprBean();
			dsBean.setId(dsBeanId);
			if (dsType.equals("driver")) {
				dsBean.setClazz(CN_DRIVERDATASOURCE);
				// driverClassName
				SprProperty dcnProp = new SprProperty();
				dcnProp.setName("driverClassName");
				dcnProp.setValue(Myjung.toNotNull(ds.getDriverClassName()));
				dsBean.addProperty(dcnProp);
				// url
				SprProperty urlProp = new SprProperty();
				urlProp.setName("url");
				urlProp.setValue(Myjung.toNotNull(ds.getUrl()));
				dsBean.addProperty(urlProp);
				// username
				SprProperty usernameProp = new SprProperty();
				usernameProp.setName("username");
				usernameProp.setValue(Myjung.toNotNull(ds.getUsername()));
				dsBean.addProperty(usernameProp);
				// password
				SprProperty passwordProp = new SprProperty();
				passwordProp.setName("password");
				passwordProp.setValue(Myjung.toNotNull(ds.getPassword()));
				dsBean.addProperty(passwordProp);
				// maxActive
				if (ds.getMaxActive() != null) {
					SprProperty maxActiveProp = new SprProperty();
					maxActiveProp.setName("maxActive");
					maxActiveProp.setValue(ds.getMaxActive());
					dsBean.addProperty(maxActiveProp);
				}
				// minIdle
				if (ds.getMinIdle() != null) {
					SprProperty minIdleProp = new SprProperty();
					minIdleProp.setName("minIdle");
					minIdleProp.setValue(ds.getMinIdle());
					dsBean.addProperty(minIdleProp);
				}
				// maxIdle
				if (ds.getMaxIdle() != null) {
					SprProperty maxIdleProp = new SprProperty();
					maxIdleProp.setName("maxIdle");
					maxIdleProp.setValue(ds.getMaxIdle());
					dsBean.addProperty(maxIdleProp);
				}
				// maxWait
				if (ds.getMaxWait() != null) {
					SprProperty maxWaitProp = new SprProperty();
					maxWaitProp.setName("maxWait");
					maxWaitProp.setValue(ds.getMaxWait());
					dsBean.addProperty(maxWaitProp);
				}
				// maxWait
				if (ds.getTimeBetweenEvictionRunsMillis() != null) {
					SprProperty timeBetweenEvictionRunsMillisProp = new SprProperty();
					timeBetweenEvictionRunsMillisProp.setName("timeBetweenEvictionRunsMillis");
					timeBetweenEvictionRunsMillisProp.setValue(ds.getTimeBetweenEvictionRunsMillis());
					dsBean.addProperty(timeBetweenEvictionRunsMillisProp);
				}
			} else if (dsType.equals("jndi")) {
				dsBean.setClazz(CN_JNDIDATASOURCE);
				// jndiName
				SprProperty jndiNameProp = new SprProperty();
				jndiNameProp.setName("jndiName");
				jndiNameProp.setValue(Myjung.toNotNull(ds.getJndiName()));
				dsBean.addProperty(jndiNameProp);
			} else {
				dsBean = null;
			}
		}

		String database = ds == null || Myjung.isEmpty(ds.getDatabase()) ? null : ds.getDatabase();
		
		SprBean efBean = null;
		SprBean lhBean = null;
		String efBeanId = toId(prefix, "entityManagerFactory");
		String sfBeanId = toId(prefix, "sessionFactory");
		SprBean sfBean = new SprBean();
		sfBean.setId(sfBeanId);
		SprProperty dsProp = new SprProperty();
		dsProp.setName("dataSource");
		dsProp.setRef(dsBeanId);
		
		if (tx != null && "jpa".equals(tx.getType())) {
			efBean = new SprBean();
			efBean.setId(efBeanId);
			efBean.setClazz(CN_ENTITYMANAGERFACTORY);
			efBean.addProperty(dsProp);
			efBean.setFactory_bean(efBeanId);
			efBean.setFactory_method("getSessionFactory");
		} else {
			String lhBeanId = toId(prefix, "lobHandler");
			String lhClassName = database != null && database.startsWith("oracle") ? CN_ORACLELOBHANDLER
					: CN_DEFAULTLOBHANDLER;
			lhBean = new SprBean();
			lhBean.setId(lhBeanId);
			lhBean.setClazz(lhClassName);
			
			sfBean.setClazz(CN_SESSIONFACTORY);
			sfBean.addProperty(dsProp);
			SprProperty lhProp = new SprProperty();
			lhProp.setName("lobHandler");
			lhProp.setRef(lhBeanId);
			sfBean.addProperty(lhProp);

			SprProperty hbPropsProp = new SprProperty();
			hbPropsProp.setName("hibernateProperties");
			SprProp hbAutoProp = new SprProp();
			hbAutoProp.setKey("hibernate.hbm2ddl.auto");
			hbAutoProp.setValue(getHibernatePropertyValue(ds, "hibernate.hbm2ddl.auto"));
			hbPropsProp.addProp(hbAutoProp);
			SprProp hbShowSqlProp = new SprProp();
			hbShowSqlProp.setKey("hibernate.show_sql");
			hbShowSqlProp.setValue(getHibernatePropertyValue(ds, "hibernate.show_sql"));
			hbPropsProp.addProp(hbShowSqlProp);
			SprProp hbFormatSqlProp = new SprProp();
			hbFormatSqlProp.setKey("hibernate.format_sql");
			hbFormatSqlProp.setValue(getHibernatePropertyValue(ds, "hibernate.format_sql"));
			hbPropsProp.addProp(hbFormatSqlProp);
			SprProp hbDialectProp = new SprProp();
			hbDialectProp.setKey("hibernate.dialect");
			hbDialectProp.setValue(Myjung.toNotNull(getHibernatePropertyValue(ds, "hibernate.dialect")));
			hbPropsProp.addProp(hbDialectProp);
			if (!Myjung.isEmpty(database) && database.equals("oracle9i")) {
				SprProp hbBatchSizeProp = new SprProp();
				hbBatchSizeProp.setKey("hibernate.jdbc.batch_size");
				hbBatchSizeProp.setValue("1");
				hbPropsProp.addProp(hbBatchSizeProp);
			}
			sfBean.addProperty(hbPropsProp);

			SprProperty mapRscsProp = new SprProperty();
			mapRscsProp.setName("mappingResources");
			if (hbmList != null)
				mapRscsProp.setList(hbmList);
			sfBean.addProperty(mapRscsProp);
		}

		// Transaction
		String txBeanId = toId(prefix, "transactionManager");

		SprBean txBean = null;
		if (tx != null && !Myjung.isEmpty(tx.getType())) {
			txBean = new SprBean();
			txBean.setId(txBeanId);
			String type = tx.getType();
			if ("hibernate".equals(type)) {
				txBean.setClazz(CN_HIBERNATETRANSACTIONMANAGER);
				SprProperty sfProp = new SprProperty();
				sfProp.setName("sessionFactory");
				sfProp.setRef(sfBeanId);
				txBean.addProperty(sfProp);
			} else if ("jpa".equals(type)) {
				txBean.setClazz(CN_JPATRANSACTIONMANAGER);
				SprProperty efProp = new SprProperty();
				efProp.setName("entityManagerFactory");
				efProp.setRef(efBeanId);
				txBean.addProperty(efProp);
			} else if ("jta".equals(type)) {
				txBean.setClazz(CN_JTATRANSACTIONMANAGER);
				if (!Myjung.isEmpty(tx.getUserTransactionName())) {
					SprProperty userTxName = new SprProperty();
					userTxName.setName("userTransactionName");
					userTxName.setValue(tx.getUserTransactionName());
					txBean.addProperty(userTxName);
				}
			}
		}

		SprBean txWrapperBean = new SprBean();
		txWrapperBean.setId(toId(prefix, "transactionManagerWrapper"));
		txWrapperBean.setClazz(CN_TRANSACTIONMANAGER);
		SprProperty txProp = new SprProperty();
		txProp.setName("transactionManager");
		txProp.setRef(txBeanId);
		txWrapperBean.addProperty(txProp);

		// Interceptors

		SprBean logAdvBean = new SprBean();
		logAdvBean.setId(toId(prefix, "loggingInterceptor"));
		logAdvBean.setClazz(CN_LOGGINGINTERCEPTER);
		SprProperty befLogProp = new SprProperty();
		befLogProp.setName("beforeLoggerEnabled");
		befLogProp.setValue("false");
		logAdvBean.addProperty(befLogProp);
		SprProperty aftLogProp = new SprProperty();
		aftLogProp.setName("afterLoggerEnabled");
		aftLogProp.setValue("false");
		logAdvBean.addProperty(aftLogProp);
		SprProperty thrLogProp = new SprProperty();
		thrLogProp.setName("throwsLoggerEnabled");
		thrLogProp.setValue("true");
		logAdvBean.addProperty(thrLogProp);

		SprBean txAdvBean = new SprBean();
		txAdvBean.setId(toId(prefix, "transactionInterceptor"));
		txAdvBean.setClazz(CN_TRANSACTIONINTERCEPTER);
		SprProperty myTxProp = new SprProperty();
		myTxProp.setName("transactionManager");
		myTxProp.setRef(toId(prefix, "transactionManagerWrapper"));
		txAdvBean.addProperty(myTxProp);

		if (dsBean != null)
			beans.addBean(dsBean);
		if (lhBean != null)
			beans.addBean(lhBean);
		if (sfBean != null)
			beans.addBean(sfBean);
		if (txBean != null)
			beans.addBean(txBean);
		beans.addBean(txWrapperBean);
		beans.addBean(logAdvBean);
		beans.addBean(txAdvBean);
	}
	private static Map<String,String> populateChildParentMap(MdlPackage pkg) {
		Map<String,String> childParentMap = new HashMap<String,String>();
		List<MdlClass> classes = pkg.getClasses();
		if (!Myjung.isEmpty(classes)) {
			for (MdlClass clazz : classes) {
				List<MdlField> fields = clazz.getFields();
				if (Myjung.isEmpty(fields))
					continue;
				for (MdlField field :fields) {
					if (Myjung.isEmpty(field.getType()) || Myjung.toBoolean(field.getReference()) || field.getType().indexOf(".") == -1)
						continue;
					childParentMap.put(field.getType(), clazz.getName());
				}
			}
		}
		return childParentMap;
	}
	protected String getHibernateDialectClassName(MdlDataSource ds) {
		if (ds == null || Myjung.isEmpty(ds.getDatabase()))
			return null;
		String database = ds.getDatabase();
		String dialect = null;
		if (database.equals("mysql")) {
			dialect = CN_MYSQLDIALECT;
		} else if (database.equals("mysql5")) {
			dialect = CN_MYSQL5DIALECT;
		} else if (database.equals("postgresql")) {
			dialect = CN_POSTGRESQLDIALECT;
		} else if (database.equals("sqlserver")) {
			dialect = CN_SQLSERVERDIALECT;
		} else if (database.equals("oracle9i")) {
			dialect = CN_ORACLE9IDIALECT;
		} else if (database.equals("oracle10g")) {
			dialect = CN_ORACLE10GDIALECT;
		} else if (database.equals("db2")) {
			dialect = CN_DB2DIALECT;
		}
		return dialect;
	}
	protected String getHibernatePropertyValue(MdlDataSource ds, String key) {
		if ("hibernate.hbm2ddl.auto".equals(key))
			return "none";
		if ("hibernate.show_sql".equals(key))
			return "false";
		if ("hibernate.format_sql".equals(key))
			return "true";
		if ("hibernate.dialect".equals(key))
			return getHibernateDialectClassName(ds);
		return null;
	}
	protected boolean getBoolean(Map<String,Object> options, String key) {
		return Myjung.toBoolean(getOption(options, key));
	}
	protected String getString(Map<String,Object> options, String key) {
		return (String) getOption(options, key);
	}
	protected Object getOption(Map<String,Object> options, String key) {
		return options == null || !options.containsKey(key)? null : options.get(key);
	}
	private static void wrapExceptionHandler(StringBuffer buf, String source,
			String exception, String tab) {
		if (tab == null)
			tab = "";
		buf.append("\r\n").append(tab).append("try {");
		buf.append(source);
		buf.append("\r\n").append(tab).append("} catch (Exception e) {");
		if (!Myjung.isEmpty(exception))
			buf.append("\r\n\t").append(tab).append("throw new ").append(
					exception).append("(e);");
		buf.append("\r\n").append(tab).append("}");
	}
	private static String generateException(String pkg, String exception) {
		StringBuffer buf = new StringBuffer();
		buf.append("package ").append(pkg).append(";\r\n");
		buf.append("\r\nimport net.myjung.exception.MyException;\r\n");
		buf.append("\r\npublic class ").append(exception).append(" extends MyException {");
		buf.append("\r\n\tprivate static final long serialVersionUID = 1L;");
		buf.append("\r\n\tpublic ").append(exception).append("() {");
		buf.append("\r\n\t\tsuper();");
		buf.append("\r\n\t}");
		buf.append("\r\n\tpublic ").append(exception).append("(String message) {");
		buf.append("\r\n\t\tsuper(message);");
		buf.append("\r\n\t}");
		buf.append("\r\n\tpublic ").append(exception).append("(String errorCode, String message) {");
		buf.append("\r\n\t\tsuper(errorCode, message);");
		buf.append("\r\n\t}");
		buf.append("\r\n\tpublic ").append(exception).append("(Throwable cause) {");
		buf.append("\r\n\t\tsuper(cause);");
		buf.append("\r\n\t}");
		buf.append("\r\n\tpublic ").append(exception).append("(String message, Throwable cause) {");
		buf.append("\r\n\t\tsuper(message, cause);");
		buf.append("\r\n\t}");
		buf.append("\r\n\tpublic ").append(exception).append("(String errorCode, String message, Throwable cause) {");
		buf.append("\r\n\t\tsuper(errorCode, message, cause);");
		buf.append("\r\n\t}");
		buf.append("\r\n}");
		return buf.toString();
	}
	
	public String getModelLibsPath() {
		return modelLibsPath;
	}
	public void setModelLibsPath(String value) {
		modelLibsPath = value;
	}
	public String getDaoLibsPath() {
		return daoLibsPath;
	}
	public void setDaoLibsPath(String value) {
		daoLibsPath = value;
	}
	public String getAdminLibsPath() {
		return adminLibsPath;
	}
	public void setAdminLibsPath(String value) {
		adminLibsPath = value;
	}
	public String getAdminSrcsPath() {
		return adminSrcsPath;
	}
	public void setAdminSrcsPath(String value) {
		adminSrcsPath = value;
	}
}
